﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

using Styx.WoWInternals.DBC;
using Styx.WoWInternals.WoWObjects;
using Styx.WoWInternals;
using Styx.Common;
using Styx.CommonBot.Routines;
using Styx.Helpers;
using Styx.Pathing;
using Styx;
using System.Diagnostics;
using System.Threading;
using System.IO;
using Styx.CommonBot;
using System.Windows.Forms;
using Styx.CommonBot.Inventory;

namespace KingWoW
{
    public class DiscPriestCombatClass : KingWoWAbstractBaseClass
    {
        
        private static string Name = "KingWoW 2 DisciplinePriest";

        #region CONSTANT AND VARIABLES
        //START OF CONSTANTS AND VARIABLES ==============================
        private static bool IsCRPaused = false;
        private static KingWoWUtility utils = null;
        private Movement movement = null;
        private ExtraUtils extra = null;

        private WoWUnit tank = null;
        private WoWUnit off_tank = null;
        private WoWUnit lastTank = null;
        private WoWUnit lastOffTank = null;
        private bool UsingAtonementHealing = true;
            
        private bool SoloBotType = false;
        private string BaseBot = "unknown";
        private TalentManager talents = null;
        //private int currentGroupForSS = 0;

        WoWUnit CurrentHealtarget = null;
        WoWUnit healTarget = null;
        WoWUnit AttackTarget = null;
        //WoWUnit ClarityWillTarget = null;
        private int SelectedGroupNumber = -1;
            
        private double RangeOfAttack = 30f;
        private bool CanPenanceOnMoving = false;

        private int PenancePercent, HealPercent, FlashHealPercent, SoLPercent, DesperatePrayerPercent;

        private const string TANK_CHANGE = "TANK CHANGED";
        private const string OFF_TANK_CHANGE = "OFFTANK CHANGED";
        private const string FACING = "FACING";

        //START OF SPELLS AND AURAS ==============================
        private const int DISPELL_MAGIC = 528;
        private const int SHACKLE_UNDEAD = 9484;
        private const int MIND_SEAR = 48045;
        private const int LEAP_OF_FAITH = 73325;
        private const int EVANGELISM = 81662;
        private const int ARCHANGEL = 81700;
        private const int PRAYER_OF_HEALING = 596;
        private const int PRAYER_OF_MENDING = 33076;
        private const int PRAYER_OF_MENDING_BUFF = 41635;
        private const int POWER_WORD_SHIELD = 17;
        private const int POWER_WORD_FORTITUDE = 21562;
        private const int POWER_WORD_SOLACE = 129250;
        private const int POWER_WORD_BARRIER = 62618;
        private const int SHADOW_WORD_PAIN = 589;
        private const int FEAR_WARD = 6346;
        private const int MASS_DISPEL = 32375;
        private const int PAIN_SUPPRESSION = 33206;
        private const int PENANCE = 47540;
        private const int POWER_INFUSION = 10060;
        private const int PURIFY = 527;
        private const int FLASH_HEAL = 2061;
        private const int HEAL = 2060;
        //private const int RENEW = 139;
        private const int SURGE_OF_LIGHT = 114255; // 1 stack --> 128654   talent spell 109186
        private const int HOLY_FIRE = 14914;
        private const int DESPERATE_PRAYER = 19236;
        private const int RESURRECTION = 2006;
        private const int SMITE = 585;
        private const int FADE = 586;
        private const int SHADOWFIEND = 34433;
        private const int MINDBENDER = 123040;
        private const int WEAKENED_SOUL = 6788;
        private const int LEVITATE = 1706;
        private const int CASCADE = 121135;
        private const int HALO = 120517;
        private const int DIVINE_STAR = 110744;
        //private const int VOID_SHIFT = 108968;
        private const int ANGELIC_FEATHER = 121536;
        private const int ANGELIC_FEATHER_AURA = 121557;
        //private const int GRACE = 47517;
        private const int GRACE = 77613;
        //private const int BINDING_HEAL = 32546;
        private const int PSYCHIC_SCREAM = 8122;
        private const int VOID_TENDRILS = 108920;
        private const int PSYFIEND = 108921;
        private const int SILENCE = 15487;
        private const int HOLY_NOVA = 132157;
        private const int CLARITY_OF_WILL = 152118;
        private const int T17_CLEAR_THOUGHTS_BUFF = 167695;
        private const int BORROWED_TIME_BUFF = 59889;
        private const string SHADOW_WORD_PAIN_STRING = "Shadow Word: Pain";
        private const string MASS_RESURRECTION = "Mass Resurrection";
        private const string SAVING_GRACE = "Saving Grace";

        private const int SPIRIT_SHELL = 109964;

        private const int DARK_INTENT = 109773;

        private const double time_dispell = 3000;

        //private const string DRINK = "Drink";
        //private const string FOOD = "Food";
        //END OF SPELLS AND AURAS ==============================
        private Random rnd = new Random();
        private int RANDOM_TIME = 0;
        //END OF CONSTANTS ==============================
        #endregion

        private bool Precombat()
        {
            if (NeedPrecombatShieldAndBuff && !Me.Combat)
            {
                if (talents.IsSelected(19) && ClarityOfWill(true)) return true;
                //Prayer of mending tank
                if (!Me.IsMoving && tank != null && tank.IsAlive && tank.Distance - tank.CombatReach - 1 <= 40 && tank.InLineOfSpellSight &&  utils.IsHealableByMe(tank))
                {
                    if (DiscPriestSettings.Instance.Use_PoM 
                        && ((tank.Guid != Me.Guid && DiscPriestSettings.Instance.RotationType != DiscPriestSettings.Rotation.PVP) || DiscPriestSettings.Instance.RotationType == DiscPriestSettings.Rotation.PVP)
                        && !utils.isMyAuraActive(PRAYER_OF_MENDING_BUFF, tank) /*&& utils.AOEHealCount(tank, 100, 20f, DiscPriestSettings.Instance.HealNPC) >= 2*/ && utils.CanCast(PRAYER_OF_MENDING))
                    {
                        utils.LogHealActivity(tank, "PRECOMBAT: PRAYER_OF_MENDING", tank.SafeName);
                        return utils.Cast(PRAYER_OF_MENDING, tank);
                    }
                }
                //Prayer of mending off_tank
                if (!Me.IsMoving && off_tank != null && off_tank.IsAlive && off_tank.Distance - off_tank.CombatReach - 1 <= 40 && off_tank.InLineOfSpellSight && utils.IsHealableByMe(off_tank))
                {
                    if (DiscPriestSettings.Instance.Use_PoM 
                        && ((off_tank.Guid != Me.Guid && DiscPriestSettings.Instance.RotationType != DiscPriestSettings.Rotation.PVP) || DiscPriestSettings.Instance.RotationType == DiscPriestSettings.Rotation.PVP)
                        && !utils.isMyAuraActive(PRAYER_OF_MENDING_BUFF, off_tank) /*&& utils.AOEHealCount(off_tank, 100, 20f, DiscPriestSettings.Instance.HealNPC) >= 2*/ && utils.CanCast(PRAYER_OF_MENDING))
                    {
                        utils.LogHealActivity(off_tank, "PRECOMBAT:  PRAYER_OF_MENDING", off_tank.SafeName);
                        return utils.Cast(PRAYER_OF_MENDING, off_tank);
                    }
                }
                //Prayer of mending player
                if (!Me.IsCasting && /*!utils.IsGlobalCooldown() &&*/ !Me.IsMoving && DiscPriestSettings.Instance.Use_PoM && utils.CanCast(PRAYER_OF_MENDING))
                {
                    WoWUnit candidatePoM = utils.GetNeedMyAuraTarget("Prayer of Mending", 40f, DiscPriestSettings.Instance.HealNPC);
                    if (candidatePoM != null)
                    {
                        utils.LogActivity("PRECOMBAT PoM: " + candidatePoM.SafeName);
                        return utils.Cast(PRAYER_OF_MENDING, candidatePoM);
                    }
                }
                if (tank != null && !tank.IsDead && tank.IsAlive && tank.Distance - tank.CombatReach - 1 <= 40 && tank.InLineOfSpellSight && utils.IsHealableByMe(tank))
                {
                    if (/*!utils.isAuraActive(POWER_WORD_SHIELD, tank) &&*/
                        (!utils.isAuraActive(WEAKENED_SOUL, tank)) && utils.CanCast(POWER_WORD_SHIELD, tank))
                    {
                        utils.LogHealActivity(tank, "PRECOMBAT TANK:  POWER_WORD_SHIELD", tank.SafeName);
                        return utils.Cast(POWER_WORD_SHIELD, tank);
                    }
                }
                if (off_tank != null && !off_tank.IsDead && off_tank.IsAlive && off_tank.Distance - off_tank.CombatReach - 1 <= 40 && off_tank.InLineOfSpellSight && utils.IsHealableByMe(off_tank))
                {
                    if (/*!utils.isAuraActive(POWER_WORD_SHIELD, off_tank) &&*/
                        (!utils.isAuraActive(WEAKENED_SOUL, off_tank)) && utils.CanCast(POWER_WORD_SHIELD, off_tank))
                    {
                        utils.LogHealActivity(off_tank, "PRECOMBAT TANK:  POWER_WORD_SHIELD", off_tank.SafeName);
                        return utils.Cast(POWER_WORD_SHIELD, off_tank);
                    }
                }
                                
            }
            return false;
        }

        #region Hotkeys
        private static Hotkey pauseHotkey, PWSHotkey, atonementHotkey, massDispelHotkey, npcHealHotkey, barrierHotkey, selectivePSW, precombatHotkey;
        
        private static bool Blanket_PWS = false;

        private static void InitializeHotkey()
        {
            if (StyxWoW.Me.Specialization == WoWSpec.PriestDiscipline)
            {
                HotkeysManager.Initialize(StyxWoW.Memory.Process.MainWindowHandle);
            }
        }

        private static Hotkey RegisterHotkeyAssignment(string name, Keys key, Action<Hotkey> callback)
        {
            Keys keyCode = key & Keys.KeyCode;
            ModifierKeys mods = ModifierKeys.NoRepeat;

            if ((key & Keys.Shift) != 0)
                mods |= ModifierKeys.Shift;
            if ((key & Keys.Alt) != 0)
                mods |= ModifierKeys.Alt;
            if ((key & Keys.Control) != 0)
                mods |= ModifierKeys.Control;

            return HotkeysManager.Register(name, keyCode, mods, callback);
        }

        private static void RegisterHotkeys()
        {
            if (StyxWoW.Me.Specialization == WoWSpec.PriestDiscipline)
            {
                precombatHotkey = RegisterHotkeyAssignment("DISCI PrecombatHotkey", (Keys)DiscPriestSettings.Instance.PrecombatHotkey, hk =>
                {
                    try
                    {
                        Logging.Write("Precombat HOTKEY PRESSED! I will buff/shield for 60 sec or until inComabt");
                        NeedPrecombatShieldAndBuff = true;
                        PrecombatTimer.AutoReset = false;
                        PrecombatTimer.Interval = 60000;
                        PrecombatTimer.Start();
                    }
                    catch (Exception e)
                    {
                        Logging.Write(e.StackTrace);
                    }
                });
                pauseHotkey = RegisterHotkeyAssignment("DISCI Routine Pause", (Keys)DiscPriestSettings.Instance.PauseKey, hk =>
                {
                    try
                    {
                        if (!IsCRPaused)
                        {
                            IsCRPaused = true;
                            if (ExtraUtilsSettings.Instance.ViewChatMessages)
                                Lua.DoString(@"print('\124cFFE61515 Paused!')");
                            Logging.Write("KingWoW Routine Paused!");
                        }
                        else
                        {
                            IsCRPaused = false;
                            if (ExtraUtilsSettings.Instance.ViewChatMessages)
                                Lua.DoString(@"print('\124cFF15E61C Resumed!')");
                            Logging.Write("KingWoW Routine Resumed!");
                        }
                    }
                    catch (Exception e)
                    {
                        Logging.Write(e.StackTrace);
                    }
                });
                atonementHotkey = RegisterHotkeyAssignment("DISCI UseDisciplineAtonementHealingRotation", (Keys)DiscPriestSettings.Instance.UseDisciplineAtonementHealingRotationKey, hk =>
                {
                    try
                    {
                        DiscPriestSettings.Instance.UseDisciplineAtonementHealingRotation = !DiscPriestSettings.Instance.UseDisciplineAtonementHealingRotation;
                        if (DiscPriestSettings.Instance.UseDisciplineAtonementHealingRotation)
                        {
                            if (ExtraUtilsSettings.Instance.ViewChatMessages)
                                Lua.DoString(@"print('UseDisciplineAtonementHealingRotation \124cFF15E61C Enabled!')");
                            Logging.Write("UseDisciplineAtonementHealingRotation Enabled!");
                        }

                        else
                        {
                            if (ExtraUtilsSettings.Instance.ViewChatMessages)
                                Lua.DoString(@"print('UseDisciplineAtonementHealingRotation \124cFFE61515 Disabled!')");
                            Logging.Write("UseDisciplineAtonementHealingRotation Disabled!");
                        }
                    }
                    catch (Exception e)
                    {
                        Logging.Write(e.StackTrace);
                    }

                });
                barrierHotkey = RegisterHotkeyAssignment("DISCI BarrierOnHotkey", (Keys)DiscPriestSettings.Instance.BarrierOnHotkey, hk =>
                {
                    try
                    {
                        Logging.Write("PW: Barrier HOTKEY PRESSED!");
                        TryPutBarrier = true;
                        HotkeyTimer.AutoReset = false;
                        HotkeyTimer.Interval = 2000;
                        HotkeyTimer.Start();
                    }
                    catch (Exception e)
                    {
                        Logging.Write(e.StackTrace);
                    }

                });
                PWSHotkey = RegisterHotkeyAssignment("DISCI Blanket_PWS_Hotkey", (Keys)DiscPriestSettings.Instance.Blanket_PWS_Hotkey, hk =>
                {
                    try
                    {
                        if (Blanket_PWS)
                        {
                            Blanket_PWS = false;
                            if (ExtraUtilsSettings.Instance.ViewChatMessages)
                                Lua.DoString(@"print('\124cFFE61515 Spam PwS STOP!')");
                            Logging.Write("Spam PwS STOP!");
                        }
                        else
                        {
                            Blanket_PWS = true;
                            if (ExtraUtilsSettings.Instance.ViewChatMessages)
                                Lua.DoString(@"print('\124cFF15E61C Spam PwS START!')");
                            Logging.Write("Spam PwS START!");
                        }
                    }
                    catch (Exception e)
                    {
                        Logging.Write(e.StackTrace);
                    }
                });
                massDispelHotkey = RegisterHotkeyAssignment("DISCI MassDispellOnHotkey", (Keys)DiscPriestSettings.Instance.MassDispellOnHotkey, hk =>
                {
                    try
                    {
                        Logging.Write("MassDispell HOTKEY PRESSED!");
                        TryPutMassDispell = true;
                        HotkeyTimer.AutoReset = false;
                        HotkeyTimer.Interval = 2000;
                        HotkeyTimer.Start();
                    }
                    catch (Exception e)
                    {
                        Logging.Write(e.StackTrace);
                    }
                });
                npcHealHotkey = RegisterHotkeyAssignment("DISCI Change_NPC_Healing_Hotkey", (Keys)DiscPriestSettings.Instance.Change_NPC_Healing_Hotkey, hk =>
                {
                    try
                    {
                        if (DiscPriestSettings.Instance.HealNPC)
                        {
                            DiscPriestSettings.Instance.HealNPC = false;
                            if (ExtraUtilsSettings.Instance.ViewChatMessages)
                                Lua.DoString(@"print('\124cFFE61515 HealNPC DISABLED!')");
                            Logging.Write("HealNPC DISABLED!");
                        }
                        else
                        {
                            DiscPriestSettings.Instance.HealNPC = true;
                            if (ExtraUtilsSettings.Instance.ViewChatMessages)
                                Lua.DoString(@"print('\124cFF15E61C HealNPC ENABLED!')");
                            Logging.Write("HealNPC ENABLED!");
                        }
                    }
                    catch (Exception e)
                    {
                        Logging.Write(e.StackTrace);
                    }
                });
                selectivePSW = RegisterHotkeyAssignment("DISCI Delective_PWS_Hotkey", (Keys)DiscPriestSettings.Instance.Selective_PWS_Hotkey, hk =>
                {
                    try
                    {
                        if (DiscPriestSettings.Instance.TargettedSelectivePW_Shield)
                        {
                            DiscPriestSettings.Instance.TargettedSelectivePW_Shield = false;
                            if (ExtraUtilsSettings.Instance.ViewChatMessages)
                                Lua.DoString(@"print('\124cFFE61515 Selective Spam PwS DISABLED!')");
                            Logging.Write("Selective Spam PwS DISABLED!");
                        }
                        else
                        {
                            DiscPriestSettings.Instance.TargettedSelectivePW_Shield = true;
                            if (ExtraUtilsSettings.Instance.ViewChatMessages)
                                Lua.DoString(@"print('\124cFF15E61C Selective Spam PwS ENABLED!')");
                            Logging.Write("Selective Spam PwS ENABLED!");
                        }
                    }
                    catch (Exception e)
                    {
                        Logging.Write(e.StackTrace);
                    }
                });
            }
        }

        private static bool TryPutBarrier = false;
        private static bool TryLButton = false;
        private static bool TryRButton = false;
        private static bool TryPutMassDispell = false;
        private static bool NeedPrecombatShieldAndBuff = false;
        private static System.Timers.Timer HotkeyTimer = new System.Timers.Timer();
        private static System.Timers.Timer PrecombatTimer = new System.Timers.Timer();

        private bool HotkeyHandle()
        {
            if (TryLButton)
            {
                utils.LogActivity("MANUAL LBUTTON On Mouse position");
                utils.PerformSingleLeftMouseClick();
                return true;
            }
            if (TryRButton)
            {
                utils.LogActivity("MANUAL LBUTTON On Mouse position");
                utils.PerformSingleRightMouseClick();
                return true;
            }
            if (TryPutMassDispell && utils.CanCast(MASS_DISPEL))
            {
                utils.LogActivity("MassDispell On Mouse position");
                utils.Cast(MASS_DISPEL);
                utils.PerformSingleLeftMouseClick();
                return true;
            }
            if (TryPutBarrier && utils.CanCast(POWER_WORD_BARRIER))
            {
                utils.LogActivity("PW: Barrier On Mouse position");
                utils.Cast(POWER_WORD_BARRIER);
                utils.PerformSingleLeftMouseClick();
                return true;
            }
            return false;
        }

        void HotkeyTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            TryLButton = false;
            TryPutBarrier = false;
            TryPutMassDispell = false;
        }

        private static void RemoveHotkeys()
        {
            if (StyxWoW.Me.Specialization == WoWSpec.PriestDiscipline)
            {
                //Holy HOTKEY
                HotkeysManager.Unregister("HOLY Routine Pause");
                HotkeysManager.Unregister("HOLY HWSanctuaryOnHotkey");
                HotkeysManager.Unregister("HOLY Blanket_RENEW_Hotkey");
                HotkeysManager.Unregister("HOLY Change_CHAKRA_Hotkey");
                HotkeysManager.Unregister("HOLY MassDispellOnHotkey");
                HotkeysManager.Unregister("HOLY Change_NPC_Healing_Hotkey");
                //Disci HOTKEY
                HotkeysManager.Unregister("DISCI Routine Pause");
                HotkeysManager.Unregister("DISCI UseDisciplineAtonementHealingRotation");
                HotkeysManager.Unregister("DISCI BarrierOnHotkey");
                HotkeysManager.Unregister("DISCI Blanket_PWS_Hotkey");
                HotkeysManager.Unregister("DISCI MassDispellOnHotkey");
                HotkeysManager.Unregister("DISCI Change_NPC_Healing_Hotkey");
                HotkeysManager.Unregister("DISCI Delective_PWS_Hotkey");
                HotkeysManager.Unregister("DISCI PrecombatHotkey");
                //shadow HOTKEY
                HotkeysManager.Unregister("SHADOW Routine Pause");
                HotkeysManager.Unregister("SHADOW MassDispellOnHotkey");
            }
        }

        private static void ReRegisterHotkeys()
        {
            if (StyxWoW.Me.Specialization == WoWSpec.PriestDiscipline)
            {
                Logging.Write("DISCIPLINE: ReRegisterHotkeys");
                RemoveHotkeys();
                RegisterHotkeys();
            }
        }
        #endregion

        private bool Interrupt()
        {
            if (DiscPriestSettings.Instance.AutoInterrupt)
            {
                WoWUnit InterruptTargetCandidate = Me.FocusedUnit;
                if (InterruptTargetCandidate == null || /*InterruptTargetCandidate.IsFriendly ||*/ InterruptTargetCandidate.IsDead
                    || !InterruptTargetCandidate.Attackable || !InterruptTargetCandidate.InLineOfSpellSight
                    || InterruptTargetCandidate.Distance - InterruptTargetCandidate.CombatReach - 1 > 30f)
                {
                    if (Me.CurrentTarget != null && Me.CurrentTarget.Distance - Me.CurrentTarget.CombatReach - 1 <= 30f && Me.CurrentTarget.InLineOfSpellSight)
                        InterruptTargetCandidate = Me.CurrentTarget;
                    else if (AttackTarget!=null && AttackTarget.Distance - AttackTarget.CombatReach - 1 <= 30f && AttackTarget.InLineOfSpellSight )
                        InterruptTargetCandidate = AttackTarget;
                }
                if (InterruptTargetCandidate != null && (InterruptTargetCandidate.IsCasting || InterruptTargetCandidate.IsChanneling)
                    && InterruptTargetCandidate.CanInterruptCurrentSpellCast && utils.CanCast(SILENCE, InterruptTargetCandidate)
                    && Me.IsFacing(InterruptTargetCandidate) 
                    && InterruptTargetCandidate.Distance - InterruptTargetCandidate.CombatReach - 1 <= 30f
                    && InterruptTargetCandidate.InLineOfSpellSight)
                {
                    RANDOM_TIME = rnd.Next(DiscPriestSettings.Instance.Interrupt_MIN_Time, DiscPriestSettings.Instance.Interrupt_MAX_Time);

                    if (InterruptTargetCandidate.CurrentCastStartTime.AddMilliseconds(RANDOM_TIME) <= DateTime.Now)
                    {
                        utils.LogActivity("SILENCE", InterruptTargetCandidate.SafeName);
                        return utils.Cast(SILENCE, InterruptTargetCandidate);
                    }
                }
            }
            return false;
        }

        private void SetAtonementVariables()
        {
            PenancePercent = DiscPriestSettings.Instance.AtonementPenancePercent;
            HealPercent = DiscPriestSettings.Instance.AtonementHealPercent;
            FlashHealPercent = DiscPriestSettings.Instance.AtonementFlashHealPercent;
            SoLPercent = DiscPriestSettings.Instance.AtonementSoLPercent;
            DesperatePrayerPercent = DiscPriestSettings.Instance.AtonementDesperatePrayerPercent;
        }

        private void SetNoAtonementVariables()
        {
            PenancePercent = DiscPriestSettings.Instance.NoAtonementPenancePercent;
            HealPercent = DiscPriestSettings.Instance.NoAtonementHealPercent;
            FlashHealPercent = DiscPriestSettings.Instance.NoAtonementFlashHealPercent;
            SoLPercent = DiscPriestSettings.Instance.NoAtonementSoLPercent;
            DesperatePrayerPercent = DiscPriestSettings.Instance.NoAtonementDesperatePrayerPercent;
        }

        public DiscPriestCombatClass()
        {
            utils = new KingWoWUtility();
            movement = new Movement();
            extra = new ExtraUtils();
            tank = null;
            lastTank = null;
            off_tank = null;
            lastOffTank = null;
            SoloBotType = false;
            BaseBot = "unknown";
            talents = new TalentManager();
            nextTimeTryReviveAllowed = DateTime.Now;
            HotkeyTimer.Elapsed += HotkeyTimer_Elapsed;
            PrecombatTimer.Elapsed += PrecombatTimer_Elapsed;
        }

        void PrecombatTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            Logging.Write("PrecombatBuff Elapsed: press again to restart 60 more sec preshield/buff");
            NeedPrecombatShieldAndBuff = false;
        }

        public override bool Pulse
        {
            get
            {
                if (IsCRPaused)
                    Logging.Write("I'm PAUSED...");
                if (Me.IsDead) return MyDeath();
                if (Me.Combat || (Me.Mounted && !DiscPriestSettings.Instance.AutoDismountOnCombat) || IsCRPaused || !StyxWoW.IsInGame || !StyxWoW.IsInWorld || Me.Silenced || utils.IsGlobalCooldown() || utils.MeIsChanneling || Me.IsCasting
                || utils.IsEatingOrDrinking())
                    return false;
                
                tank = utils.SimpleGetTank(40f);
                if (tank == null || !tank.IsValid || !tank.IsAlive) tank = Me;

                if (tank != null && (lastTank == null || lastTank.Guid != tank.Guid))
                {
                    lastTank = tank;
                    utils.LogActivity(TANK_CHANGE, tank.SafeName);
                }
                off_tank = utils.SimpleGetOffTank(40f, tank);
                if (off_tank != null && (lastOffTank == null || lastOffTank.Guid != off_tank.Guid))
                {
                    lastOffTank = off_tank;
                    utils.LogActivity(OFF_TANK_CHANGE, off_tank.SafeName);
                }
                if (DiscPriestSettings.Instance.BurstSpeedMoving && Me.IsMoving && !Me.Mounted && !Me.IsFalling && !Me.IsDead && !Me.IsGhost
                    && Me.MovementInfo.TimeMoved >= DiscPriestSettings.Instance.MoveTimeForSpeedBuff && !IsCRPaused)
                {
                    if (talents.IsSelected(5) && !utils.isAuraActive(ANGELIC_FEATHER_AURA) && utils.CanCast(ANGELIC_FEATHER))
                    {
                        utils.LogActivity("moving....ANGELIC_FEATHER");
                        utils.Buff(ANGELIC_FEATHER);
                        SpellManager.ClickRemoteLocation(Me.Location);
                        Lua.DoString("SpellStopTargeting()");
                        return true;
                    }
                    if (talents.IsSelected(4) && !utils.isAuraActive(WEAKENED_SOUL, Me) /*&& !utils.isAuraActive(POWER_WORD_SHIELD, Me)*/ && utils.CanCast(POWER_WORD_SHIELD))
                    {
                        utils.LogActivity("moving....POWER_WORD_SHIELD");
                        return utils.Cast(POWER_WORD_SHIELD, Me);
                    }

                }
                healTarget = utils.GetHealTarget(40f, DiscPriestSettings.Instance.HealNPC);
                if (Precombat()) return true;
                HotkeyHandle();
                //full party or me
                if (!Me.Combat && !IsCRPaused && !Me.Mounted && DiscPriestSettings.Instance.OOCHealing)
                {
                    Resurrect();
                    if (healTarget != null)
                    {
                        double hp = healTarget.HealthPercent;
                        if (utils.isAuraActive(SURGE_OF_LIGHT)
                            && utils.CanCast(FLASH_HEAL)
                            && (hp <= SoLPercent
                                || Me.GetAuraById(SURGE_OF_LIGHT).TimeLeft.TotalMilliseconds <= 3500
                                || utils.PlayerCountBuff(SURGE_OF_LIGHT) == 2))
                        {
                            utils.LogHealActivity(healTarget, " FLASH_HEAL", healTarget.SafeName);
                            return utils.Cast(FLASH_HEAL, healTarget);
                        }
                        if (  utils.GetSpellCooldown(PENANCE).TotalMilliseconds <= 2 * StyxWoW.WoWClient.Latency && hp <= PenancePercent && (!Me.IsMoving || CanPenanceOnMoving))
                        {
                            utils.LogHealActivity(healTarget, " PENANCE", healTarget.SafeName);
                            return utils.Cast(PENANCE, healTarget);
                        }
                        if (!Me.IsCasting && !Me.IsChanneling && !utils.IsGlobalCooldown() && utils.CanCast(HOLY_NOVA)
                        && utils.GetMemberCountBelowThresholdInRangeFromPlayer(DiscPriestSettings.Instance.HolyNovaPercent, Me, 12, DiscPriestSettings.Instance.HealNPC) >= DiscPriestSettings.Instance.HolyNovaNumber)
                        {
                            utils.LogActivity("HOLY_NOVA");
                            return utils.Cast(HOLY_NOVA);
                        }
                        if (!Me.IsMoving && hp <= HealPercent && utils.CanCast(HEAL))
                        {
                            utils.LogHealActivity(healTarget, " HEAL", healTarget.SafeName);
                            CurrentHealtarget = healTarget;
                            return utils.Cast(HEAL, healTarget);
                        }
                    }
                }
                if (!IsCRPaused && !Me.Combat && ((tank != null && tank.Combat) || (off_tank != null && off_tank.Combat)))
                    return CombatRotation();
                return false;
            }
        }

        public override bool Initialize
        {
            get
            {
                Logging.Write("Ciao " + Me.SafeName);
                Logging.Write("Welcome to " + Name + " custom class");
                Logging.Write("Tanks All HonorBuddy Forum developers for code inspiration!");
                Logging.Write("Powered by Attilio76");
                BotEvents.OnBotStartRequested += new BotEvents.OnBotStartStopRequestedDelegate(BotEvents_OnBotStart);
                Logging.Write("Initializing Hotkey");
                InitializeHotkey();
                ReRegisterHotkeys();
                Logging.Write("************ XML CONFIGURATION ************");
                Logging.Write(DiscPriestSettings.Instance.GetXML().ToString());
                Logging.Write("*******************************************");
                Logging.Write("*******************************************");
                Logging.Write("*******************************************");
                Logging.Write("************ EXTRA CONFIGURATION ************");
                Logging.Write(ExtraUtilsSettings.Instance.GetXML().ToString());
                Logging.Write("*******************************************");
                return true; ;
            }
        }

        public override bool UpdateTalentAndGlyph
        {
            get 
            {
                talents.Update();

                if (talents.HasGlyph("Holy Fire"))
                {
                    Logging.Write("Glyph of Holy Fire Detected: range of attack spells incremented to 40");
                    RangeOfAttack = 40f;
                }
                else
                    Logging.Write("NO Glyph of Holy Fire Detected");
                if (talents.HasGlyph("Penance"))
                {
                    Logging.Write("Glyph of Penance Detected: penance on moving allower");
                    CanPenanceOnMoving = true;
                }
                else
                    Logging.Write("NO Glyph of Penance Detected");
                BotUpdate();
                ReRegisterHotkeys();
                return true;
            
            }
        }

        void BotEvents_OnBotStart(EventArgs args)
        {
            talents.Update();

            if (talents.HasGlyph("Holy Fire"))
            {
                Logging.Write("Glyph of Holy Fire Detected: range of attack spells incremented to 40");
                RangeOfAttack = 40f;
            }
            else
                Logging.Write("NO Glyph of Holy Fire Detected");
            if (talents.HasGlyph("Penance"))
            {
                Logging.Write("Glyph of Penance Detected: penance on moving allower");
                CanPenanceOnMoving = true;
            }
            else
                Logging.Write("NO Glyph of Penance Detected");
            BotUpdate();
            ReRegisterHotkeys();
        }

        public override bool NeedRest
        {
            get
            {
                if (Me.IsDead || Me.Mounted || Me.InVehicle || (Me.HealthPercent >= 100 && Me.ManaPercent >= 100)) return false;
                if (utils.IsEatingOrDrinking())
                    return true;
                if (Me.ManaPercent <= DiscPriestSettings.Instance.ManaPercent
                    && !Me.Combat && !Me.IsMoving && !utils.IsEatingOrDrinking())
                {
                    WoWItem mydrink = Consumable.GetBestDrink(false);
                    if (mydrink != null)
                    {
                        utils.LogActivity("Drinking");
                        Styx.CommonBot.Rest.DrinkImmediate();
                        return true;
                    }
                    return true;
                }
                if (Me.HealthPercent <= DiscPriestSettings.Instance.HealthPercent
                    && !Me.Combat && !Me.IsMoving && !utils.IsEatingOrDrinking())
                {
                    WoWItem myfood = Consumable.GetBestFood(false);
                    if (myfood != null)
                    {
                        utils.LogActivity("Eating");
                        Styx.CommonBot.Rest.DrinkImmediate();
                        return true;
                    }
                    return true;
                }
                return false;
            }
        }

        public override bool NeedPullBuffs { 
            get 
            {
                return DisciPullBuff(); 
            } 
        }

        public override bool NeedCombatBuffs { get { return Buff(); } }

        public override bool NeedPreCombatBuffs { get { return Buff(); } }

        private DateTime nextTimeTryReviveAllowed;
        
        public void SetNextTimeTryRevive()
        {
            //2 seconds avoid duuble cast
            nextTimeTryReviveAllowed = DateTime.Now + new TimeSpan(0, 0, 0, 0, 3000);
        }

        private bool MyDeath()
        {
            if (SoloBotType && Me.IsDead && !Me.IsGhost && nextTimeTryReviveAllowed < DateTime.Now)
            {
                Lua.DoString(string.Format("RunMacroText(\"{0}\")", "/script RepopMe()"));
                SetNextTimeTryRevive();
            }
            return false;
        }

        public override bool Pull
        {
            get 
            {
                AttackTarget = Me.CurrentTarget;
                if (AttackTarget != null && AttackTarget.IsDead)
                {
                    Me.ClearTarget();
                    AttackTarget = utils.getTargetToAttack(40, tank, false, ExtraUtilsSettings.Instance.UseBossLogic);
                    AttackTarget.Target();
                }
                if ((SoloBotType || DiscPriestSettings.Instance.movementEnabled) && Me.CurrentTarget != null && Me.IsMoving && Me.CurrentTarget.InLineOfSpellSight && Me.CurrentTarget.Distance - Me.CurrentTarget.CombatReach - 1 <= DiscPriestSettings.Instance.PullDistance)
                {
                    Navigator.PlayerMover.MoveStop();
                }
                if (AttackTarget != null && /*!AttackTarget.IsFriendly &&*/ AttackTarget.Attackable && !AttackTarget.IsDead && !IsCRPaused)
                {
                    if (!AttackTarget.InLineOfSpellSight || AttackTarget.Distance - AttackTarget.CombatReach -1  > DiscPriestSettings.Instance.PullDistance)
                    {
                        //Logging.Write("pull: AttackTarget distance=" + AttackTarget.Distance + " moving in range");
                        movement.KingHealMove(AttackTarget, DiscPriestSettings.Instance.PullDistance);
                    }
                    if (!Me.IsFacing(AttackTarget) && (DiscPriestSettings.Instance.AutofaceTarget || SoloBotType) && !Me.IsMoving)
                    {
                        Me.SetFacing(AttackTarget);
                    }

                    if (utils.GetSpellCooldown(PENANCE).TotalMilliseconds <= 2 * StyxWoW.WoWClient.Latency && (!Me.IsMoving || (Me.IsMoving && CanPenanceOnMoving)))
                    {
                        utils.LogActivity("PULL: PENANCE", AttackTarget.SafeName);
                        return utils.Cast(PENANCE, AttackTarget);
                    }

                    if (!Me.IsChanneling && talents.IsSelected(9) && Me.IsFacing(AttackTarget) && utils.CanCast(POWER_WORD_SOLACE))
                    {
                        utils.LogActivity("PULL: POWER_WORD_SOLACE", AttackTarget.SafeName);
                        return utils.Cast(POWER_WORD_SOLACE, AttackTarget);
                    }

                    if (!Me.IsChanneling && !talents.IsSelected(9) && utils.CanCast(HOLY_FIRE, AttackTarget, true) /*&& !Me.IsMoving*/)
                    {
                        utils.LogActivity("PULL: HOLY_FIRE", AttackTarget.SafeName);
                        return utils.Cast(HOLY_FIRE, AttackTarget);
                    } 

                    if (DiscPriestSettings.Instance.UseSWP && !utils.isAuraActive(SHADOW_WORD_PAIN, AttackTarget) && utils.CanCast(SHADOW_WORD_PAIN, AttackTarget, true))
                    {
                        utils.LogActivity("PULL: SHADOW_WORD_PAIN", AttackTarget.SafeName);
                        return utils.Cast(SHADOW_WORD_PAIN, AttackTarget);
                    }

                    if (!Me.IsCasting && !Me.IsChanneling && !utils.IsGlobalCooldown() && utils.CanCast(SMITE) && !Me.IsMoving)
                    {
                        utils.LogActivity("PULL: SMITE", AttackTarget.SafeName);
                        return utils.Cast(SMITE, AttackTarget);
                    }

                }
                return false;          
            }
        }

        private bool DisciPullBuff()
        {
            

            if(!DiscPriestSettings.Instance.fastPull)
            {
                if (utils.Mounted() || IsCRPaused)
                    return false;
                if (!DiscPriestSettings.Instance.fastPull && !utils.isAuraActive(POWER_WORD_FORTITUDE) && utils.CanCast(POWER_WORD_FORTITUDE))
                {
                    utils.LogActivity("POWER_WORD_FORTITUDE");
                    utils.Cast(POWER_WORD_FORTITUDE);
                }
                foreach (WoWPlayer player in Me.PartyMembers)
                {
                    if (player.Distance - player.CombatReach -1  > 40f || player.IsDead || player.IsGhost || !player.InLineOfSpellSight) continue;
                    else if (!utils.isAuraActive(POWER_WORD_FORTITUDE, player) && utils.CanCast(POWER_WORD_FORTITUDE))
                    {
                        utils.LogActivity("POWER_WORD_FORTITUDE", player.SafeName);
                        utils.Cast(POWER_WORD_FORTITUDE, player);
                    }
                }
                if (DiscPriestSettings.Instance.UseFearWard && utils.CanCast(FEAR_WARD) && !utils.isAuraActive(FEAR_WARD, Me))
                {
                    utils.LogActivity("FEAR_WARD", Me.SafeName);
                    return utils.Cast(FEAR_WARD, Me);
                }
                if (/*!utils.isAuraActive(POWER_WORD_SHIELD) &&*/ (!utils.isAuraActive(WEAKENED_SOUL,Me)  ) && utils.CanCast(POWER_WORD_SHIELD))
                {
                    utils.LogActivity("POWER_WORD_SHIELD", Me.SafeName);
                    utils.Cast(POWER_WORD_SHIELD, Me); //no return see below
                }
            }
            
            return false; //return false or loop trying cast PULLBUFF (not implemented)
        }

        private bool BotUpdate()
        {
            if (BaseBot.Equals(BotManager.Current.Name))
                return false;
            if (utils.IsBotBaseInUse("LazyRaider") || utils.IsBotBaseInUse("Tyrael")
                || utils.IsBotBaseInUse("Raid Bot") || utils.IsBotBaseInUse("Enyo"))
            {
                SoloBotType = false;
                BaseBot = BotManager.Current.Name;
                Logging.Write("Base bot detected: " + BotManager.Current.Name);
                return true;
            }

            Logging.Write("Base bot detected: " + BotManager.Current.Name);
            SoloBotType = true;
            BaseBot = BotManager.Current.Name;
            return true;


        }
        
        private bool ManaRegen()
        {
            
                
            if (AttackTarget != null && Me.Combat && Me.Combat && !Me.IsChanneling && talents.IsSelected(9) && utils.CanCast(POWER_WORD_SOLACE))
            {
                if (!Me.IsFacing(AttackTarget) && !Me.IsMoving)
                    AttackTarget.Face();
                if (Me.IsFacing(AttackTarget))
                {
                    utils.LogActivity("POWER_WORD_SOLACE", AttackTarget.SafeName);
                    return utils.Cast(POWER_WORD_SOLACE, AttackTarget);
                }
            }
            if (Me.Combat && AttackTarget != null &&
                ((DiscPriestSettings.Instance.CDUsePet == DiscPriestSettings.CDUseType.BOSS && extra.IsTargetBoss())
                    || DiscPriestSettings.Instance.CDUsePet == DiscPriestSettings.CDUseType.COOLDOWN))
            {
                if (Me.ManaPercent <= DiscPriestSettings.Instance.ShadowFiendPercent && utils.CanCast(SHADOWFIEND))
                {
                    utils.LogActivity("SHADOWFIEND", AttackTarget.SafeName);
                    return utils.Cast(SHADOWFIEND, AttackTarget);
                }

                else if (Me.ManaPercent <= DiscPriestSettings.Instance.ShadowFiendPercent && utils.CanCast(MINDBENDER))
                {
                    utils.LogActivity("MINDBENDER", AttackTarget.SafeName);
                    return utils.Cast(MINDBENDER, AttackTarget);
                }
            }

            return false;
        }

        private bool Self()
        {
            
            if (Me.Combat && Me.HealthPercent <= DesperatePrayerPercent && utils.CanCast(DESPERATE_PRAYER))
            {
                utils.LogHealActivity(Me,"DESPERATE_PRAYER");
                return utils.Cast(DESPERATE_PRAYER);
            }

            /*if (DiscPriestSettings.Instance.RotationType == DiscPriestSettings.Rotation.PVP
                && !utils.isAuraActive(POWER_WORD_SHIELD) && (!utils.isAuraActive(WEAKENED_SOUL)  ) && utils.CanCast(POWER_WORD_SHIELD))
            {
                utils.LogHealActivity(Me, "POWER_WORD_SHIELD", Me.SafeName);
                return utils.Cast(POWER_WORD_SHIELD, Me);
            }*/

            if (Me.Combat && DiscPriestSettings.Instance.SelfHealingPriorityEnabled && Me.HealthPercent <= DiscPriestSettings.Instance.SelfHealingPriorityHP)
            {
                if (utils.GetSpellCooldown(PENANCE).TotalMilliseconds <= 2 * StyxWoW.WoWClient.Latency && (!Me.IsMoving || CanPenanceOnMoving))
                {
                    utils.LogHealActivity(Me, "Heal Me priority: PENANCE", Me.SafeName);
                    return utils.Cast(PENANCE, Me);
                }
                //Surge of Light
                if (utils.isAuraActive(SURGE_OF_LIGHT))
                {
                    utils.LogHealActivity(Me, "Heal Me priority: Surge of light:" + FLASH_HEAL, Me.SafeName);
                    return utils.Cast(FLASH_HEAL, Me);
                }
                if (DiscPriestSettings.Instance.UseFade && Me.Combat && (Me.GroupInfo.IsInParty || Me.GroupInfo.IsInRaid) && (Targeting.GetAggroOnMeWithin(Me.Location, 100) > 0) && utils.CanCast(FADE))
                {
                    utils.LogActivity("FADE");
                    return utils.Cast(FADE);
                }
                if (/*!utils.isAuraActive(POWER_WORD_SHIELD) &&*/ (!utils.isAuraActive(WEAKENED_SOUL,Me)) && utils.CanCast(POWER_WORD_SHIELD))
                {
                    utils.LogHealActivity(Me, "Heal Me priority: POWER_WORD_SHIELD", Me.SafeName);
                    return utils.Cast(POWER_WORD_SHIELD, Me);
                }
                if (Me.HealthPercent <= FlashHealPercent && utils.CanCast(FLASH_HEAL) && utils.GetSpellCooldown(PENANCE).TotalMilliseconds > 2 * StyxWoW.WoWClient.Latency)
                {
                    utils.LogHealActivity(Me, "Heal Me priority: FLASH_HEAL", Me.SafeName);
                    CurrentHealtarget = Me;
                    return utils.Cast(FLASH_HEAL,Me);
                }               
                if (Me.HealthPercent <= HealPercent && utils.CanCast(HEAL))
                {
                    utils.LogHealActivity(Me, "Heal Me priority: HEAL", Me.SafeName);
                    CurrentHealtarget = Me;
                    return utils.Cast(HEAL,Me);
                }            
            }

            if (Me.Combat && !Me.IsChanneling && utils.CanCast(ARCHANGEL) && (utils.PlayerCountBuff("Evangelism") == 5 ) && DiscPriestSettings.Instance.UseArchangel)
            {
                utils.LogActivity("ARCHANGEL");
                return utils.Cast(ARCHANGEL);
            }

             //power infusion for heal burst or mana low
            if (utils.CanCast(POWER_INFUSION) && Me.Combat && !utils.isAuraActive(POWER_INFUSION) && 
                ((utils.GetMemberCountBelowThreshold(DiscPriestSettings.Instance.PowerInfusionPercent) >= DiscPriestSettings.Instance.PowerInfusionNumber) ||
                Me.ManaPercent <= DiscPriestSettings.Instance.PowerInfusionManaPercent) )
            {
                utils.LogActivity("POWER_INFUSION");
                return utils.Cast(POWER_INFUSION);
            }

            /*if (DiscPriestSettings.Instance.MantainBorrowedTime && Me.Combat && !utils.isAuraActive(BORROWED_TIME_BUFF))
            {
                WoWUnit PWS_Target = utils.GetTargetToShield(40f, DiscPriestSettings.Instance.HealNPC);
                if (PWS_Target != null)
                {
                    utils.LogActivity("MANTAIN Borrowed Time: cast PWS to" + PWS_Target.SafeName);
                    return utils.Cast(POWER_WORD_SHIELD,PWS_Target);
                }
            }*/
            return false;
        }
  
        private bool AoE()
        {
            if (Me.Combat && utils.CanCast(POWER_WORD_BARRIER) && DiscPriestSettings.Instance.AutoUsePWBarrier)
            {
                WoWUnit pwb_target = utils.BestPWBTargetLocation(DiscPriestSettings.Instance.PWBarrierPercent, DiscPriestSettings.Instance.PWBarrierNumber);
                if (pwb_target != null)
                {
                    utils.LogActivity("POWER_WORD_BARRIER", pwb_target.SafeName);
                    utils.Cast(POWER_WORD_BARRIER);
                    return SpellManager.ClickRemoteLocation(pwb_target.Location);
                }
            }

            if (!DiscPriestSettings.Instance.DisableAOE_HealingRotation)
            {
                //divine star
                if(!Me.IsMoving && utils.CanCast(DIVINE_STAR))
                {
                    WoWUnit ds_target = utils.BestDSTarget(DiscPriestSettings.Instance.CascadeHaloDivinestarPercent, DiscPriestSettings.Instance.CascadeHaloDivineStarNumber);
                    if (ds_target != null && utils.CanCast(DIVINE_STAR,ds_target,true))
                    {
                        ds_target.Face();
                        utils.LogActivity("DIVINE_STAR", ds_target.SafeName);
                        return utils.Cast(DIVINE_STAR,ds_target);
                    }
                }

                if ((utils.GetMemberCountBelowThreshold(DiscPriestSettings.Instance.CascadeHaloDivinestarPercent, 40, DiscPriestSettings.Instance.HealNPC) >= DiscPriestSettings.Instance.CascadeHaloDivineStarNumber))
                {
                    if (utils.CanCast(HALO))
                    {
                        utils.LogActivity("HALO");
                        return utils.Cast(HALO);
                    }
                    else if (utils.CanCast(CASCADE))
                    {
                        utils.LogActivity("CASCADE");
                        return utils.Cast(CASCADE);
                    }
                }

                if (utils.CanCast(PRAYER_OF_HEALING) && !Me.IsMoving)
                {
                    WoWUnit poh_target = null;
                    poh_target = utils.BestPoHTarget(DiscPriestSettings.Instance.PrayerOfHealingPercent, DiscPriestSettings.Instance.PrayerOfHealingNumber/*,true*/,DiscPriestSettings.Instance.HealNPC);
                    if (poh_target != null)
                    {
                        if (DiscPriestSettings.Instance.UseSS_on_POM && utils.CanCast(SPIRIT_SHELL))
                        {
                            utils.LogActivity("SPIRIT SHELL Before Prayer of Healing");
                            utils.Cast(SPIRIT_SHELL);
                        }
                        utils.LogActivity("PRAYER_OF_HEALING", poh_target.SafeName);
                        return utils.Cast(PRAYER_OF_HEALING, poh_target);
                    }
                }

                if (!Me.IsCasting && !Me.IsChanneling && !utils.IsGlobalCooldown() && utils.CanCast(HOLY_NOVA) &&
                    utils.GetMemberCountBelowThresholdInRangeFromPlayer(DiscPriestSettings.Instance.HolyNovaPercent, Me, 12, DiscPriestSettings.Instance.HealNPC) >= DiscPriestSettings.Instance.HolyNovaNumber)
                {
                    utils.LogActivity("HOLY_NOVA");
                    return utils.Cast(HOLY_NOVA);
                }
            }

            return false;
        }
       
        private bool SoloHealing()
        {
            double hp = Me.HealthPercent;

            //Surge of Light
            if (utils.isAuraActive(SURGE_OF_LIGHT)
                            && utils.CanCast(FLASH_HEAL)
                            && (hp <= SoLPercent
                                || Me.GetAuraById(SURGE_OF_LIGHT).TimeLeft.TotalMilliseconds <= 3500
                                || utils.PlayerCountBuff(SURGE_OF_LIGHT) == 2))
            {
                utils.LogHealActivity(Me,"FLASH_HEAL", Me.SafeName);
                return utils.Cast(FLASH_HEAL, Me);
            }
            if (hp <= PenancePercent && utils.GetSpellCooldown(PENANCE).TotalMilliseconds <= 2 * StyxWoW.WoWClient.Latency && (!Me.IsMoving || CanPenanceOnMoving))
            {
                utils.LogHealActivity(Me," PENANCE", Me.SafeName);
                return utils.Cast(PENANCE, Me);
            }
            if (/*!utils.isAuraActive(POWER_WORD_SHIELD) &&*/ (!utils.isAuraActive(WEAKENED_SOUL,Me)  ) && utils.CanCast(POWER_WORD_SHIELD))
            {
                utils.LogHealActivity(Me," POWER_WORD_SHIELD", Me.SafeName);
                return utils.Cast(POWER_WORD_SHIELD, Me);
            }

            if (hp <= FlashHealPercent && utils.CanCast(FLASH_HEAL) && !Me.IsMoving && utils.isAuraActive(WEAKENED_SOUL))
            {
                utils.LogHealActivity(Me," FLASH_HEAL", Me.SafeName);
                CurrentHealtarget = Me;
                return utils.Cast(FLASH_HEAL, Me);
            }          
            if (hp <= DiscPriestSettings.Instance.PainSuppressionPercent && utils.CanCast(PAIN_SUPPRESSION) && DiscPriestSettings.Instance.UsePainSuppression)
            {
                utils.LogHealActivity(Me," PAIN_SUPPRESSION", Me.SafeName);
                return utils.Cast(PAIN_SUPPRESSION, Me);
            }
            return false;
        }

        private bool Atonement()
        {
            if (DiscPriestSettings.Instance.AtonementHp < 100 && utils.GetMemberCountBelowThreshold(DiscPriestSettings.Instance.AtonementHp, 40, DiscPriestSettings.Instance.HealNPC) == 0)
                return false;
            
            //Atonement heal
            if (AttackTarget != null)
            {
                if (DiscPriestSettings.Instance.movementEnabled && (AttackTarget.Distance - AttackTarget.CombatReach - 1 > DiscPriestSettings.Instance.PullDistance || !AttackTarget.InLineOfSpellSight))
                    movement.KingHealMove(AttackTarget, DiscPriestSettings.Instance.PullDistance);

                if (!Me.IsMoving && (DiscPriestSettings.Instance.AutofaceTarget || SoloBotType))
                {
                    Me.SetFacing(AttackTarget);
                }
                if (DiscPriestSettings.Instance.UsePenanceInDPS && utils.GetSpellCooldown(PENANCE).TotalMilliseconds <= 2 * StyxWoW.WoWClient.Latency && (!Me.IsMoving || CanPenanceOnMoving))
                {
                    utils.LogActivity("PENANCE", AttackTarget.SafeName);
                    return utils.Cast(PENANCE, AttackTarget);
                }
                if (!Me.IsChanneling && !talents.IsSelected(9) && utils.CanCast(HOLY_FIRE))
                {
                    utils.LogActivity("HOLY_FIRE", AttackTarget.SafeName);
                    return utils.Cast(HOLY_FIRE, AttackTarget);
                }
                if (!Me.IsChanneling && !Me.IsCasting && !utils.IsGlobalCooldown() && utils.CanCast(HOLY_NOVA) && utils.AllAttaccableEnemyMobsInRange(12).Count() >= DiscPriestSettings.Instance.HolyNovaEnemiesNumber)
                {
                    utils.LogActivity("HOLY_NOVA");
                    return utils.Cast(HOLY_NOVA);
                }
                /*if (DiscPriestSettings.Instance.HelpDPS && !Me.IsChanneling && utils.MyAuraTimeLeft(SHADOW_WORD_PAIN, AttackTarget) < 5400 && utils.CanCast(SHADOW_WORD_PAIN))
                {
                    utils.LogActivity("SHADOW_WORD_PAIN", AttackTarget.SafeName);
                    return utils.Cast(SHADOW_WORD_PAIN, AttackTarget);
                }*/
                if (!Me.IsCasting && !Me.IsChanneling && !utils.IsGlobalCooldown() && utils.CanCast(SMITE) && !Me.IsMoving)
                {
                    utils.LogActivity("SMITE", AttackTarget.SafeName);
                    return utils.Cast(SMITE, AttackTarget);
                }
            }
            return false;            
        }

        private bool Healing()
        {
            if (DiscPriestSettings.Instance.MantainBorrowedTime && Me.Combat && !utils.isAuraActive(BORROWED_TIME_BUFF))
            {
                WoWUnit PWS_Target = utils.GetTargetToShield(40f, DiscPriestSettings.Instance.HealNPC);
                if (PWS_Target != null)
                {
                    utils.LogActivity("MANTAIN Borrowed Time: cast PWS to" + PWS_Target.SafeName);
                    return utils.Cast(POWER_WORD_SHIELD, PWS_Target);
                }
            }
            //we are targetting an npc to full: if we are at this point then our healing settings cant full
            //the target so we spam Heal
            if (DiscPriestSettings.Instance.HealNPC && DiscPriestSettings.Instance.FullSelectedNPC
                && !Me.IsCasting && !utils.IsGlobalCooldown()
                && Me.CurrentTarget != null && Me.CurrentTarget.IsFriendly && !Me.CurrentTarget.Attackable && !Me.CurrentTarget.IsPlayer
                && !Me.CurrentTarget.IsDead && Me.CurrentTarget.HealthPercent < 99
                && Me.CurrentTarget.Distance - Me.CurrentTarget.CombatReach - 1 <= 40f && Me.CurrentTarget.InLineOfSpellSight)
            {
                if (/*!utils.isAuraActive(POWER_WORD_SHIELD, Me.CurrentTarget) &&*/
                    (!utils.isAuraActive(WEAKENED_SOUL, Me.CurrentTarget)) && utils.CanCast(POWER_WORD_SHIELD, Me.CurrentTarget))
                {
                    utils.LogHealActivity(healTarget, "FULL NPC CURRENT TARGET: POWER_WORD_SHIELD", Me.CurrentTarget.SafeName);
                    return utils.Cast(POWER_WORD_SHIELD, Me.CurrentTarget);
                }
                if (utils.GetSpellCooldown(PENANCE).TotalMilliseconds <= 2 * StyxWoW.WoWClient.Latency && (!Me.IsMoving || CanPenanceOnMoving))
                {
                    utils.LogHealActivity(Me.CurrentTarget, "FULL NPC CURRENT TARGET: PENANCE", Me.CurrentTarget.SafeName);
                    return utils.Cast(PENANCE, Me.CurrentTarget);
                }
                if (!Me.IsMoving && Me.CurrentTarget.HealthPercent < 50 && !Me.IsCasting && !utils.IsGlobalCooldown() && utils.CanCast(FLASH_HEAL))
                {
                    utils.LogHealActivity(Me.CurrentTarget, "FULL NPC CURRENT TARGET: FLASH_HEAL", Me.CurrentTarget.SafeName);
                    return utils.Cast(FLASH_HEAL, Me.CurrentTarget);
                }
                if (!Me.IsMoving && !Me.IsCasting && !utils.IsGlobalCooldown() && utils.CanCast(HEAL))
                {
                    utils.LogHealActivity(Me.CurrentTarget, "FULL NPC CURRENT TARGET: HEAL", Me.CurrentTarget.SafeName);
                    CurrentHealtarget = Me.CurrentTarget;
                    return utils.Cast(HEAL, Me.CurrentTarget);
                }
            }

            if (healTarget != null)
            {
                double hp = healTarget.HealthPercent;

                //SAVING GRACE
                if (utils.CanCast(SAVING_GRACE) && healTarget.HealthPercent <= DiscPriestSettings.Instance.SavingGraceHP
                        && utils.PlayerCountBuff(SAVING_GRACE) <= DiscPriestSettings.Instance.SavinGraceDebuffStackNumber)
                {
                    utils.LogHealActivity(healTarget, "SOS:   SAVING GRACE", healTarget.SafeName);
                    return utils.Cast(SAVING_GRACE, healTarget);
                }

                //Surge of Light
                if (utils.isAuraActive(SURGE_OF_LIGHT)
                        && utils.CanCast(FLASH_HEAL)
                        && (hp <= SoLPercent
                            || Me.GetAuraById(SURGE_OF_LIGHT).TimeLeft.TotalMilliseconds <= 3500
                            || utils.PlayerCountBuff(SURGE_OF_LIGHT) == 2))
                {
                    utils.LogHealActivity(healTarget, "SoL Proc: FLASH_HEAL", healTarget.SafeName);
                    return utils.Cast(FLASH_HEAL, healTarget);
                }
                if (hp <= DiscPriestSettings.Instance.PWShieldPercent /*&& !utils.isAuraActive(POWER_WORD_SHIELD, healTarget)*/
                    && (!utils.isAuraActive(WEAKENED_SOUL, healTarget)) && utils.CanCast(POWER_WORD_SHIELD, healTarget))
                {
                    utils.LogHealActivity(healTarget, " POWER_WORD_SHIELD", healTarget.SafeName);
                    return utils.Cast(POWER_WORD_SHIELD, healTarget);
                }
                if (hp <= PenancePercent && utils.GetSpellCooldown(PENANCE).TotalMilliseconds <= 2 * StyxWoW.WoWClient.Latency && (!Me.IsMoving || CanPenanceOnMoving) )
                { 
                    utils.LogHealActivity(healTarget, " PENANCE", healTarget.SafeName);
                    return utils.Cast(PENANCE, healTarget);
                }               
                if (!DiscPriestSettings.Instance.UsePainSuppressionOnlyOnTank && hp <= DiscPriestSettings.Instance.PainSuppressionPercent && utils.CanCast(PAIN_SUPPRESSION) && DiscPriestSettings.Instance.UsePainSuppression)
                {
                    utils.LogHealActivity(healTarget, " PAIN_SUPPRESSION", healTarget.SafeName);
                    return utils.Cast(PAIN_SUPPRESSION, healTarget);
                }
                if (hp <= FlashHealPercent && utils.CanCast(FLASH_HEAL) && !Me.IsMoving && !utils.IsGlobalCooldown() && !Me.IsCasting
                    && utils.GetSpellCooldown(PENANCE).TotalMilliseconds > 2 * StyxWoW.WoWClient.Latency)
                {
                    utils.LogHealActivity(healTarget, " FLASH_HEAL", healTarget.SafeName);
                    CurrentHealtarget = healTarget;
                    return utils.Cast(FLASH_HEAL, healTarget);
                }
                if (AttackTarget != null && Me.Combat && Me.IsFacing(AttackTarget) && !Me.IsChanneling && talents.IsSelected(9) && utils.CanCast(POWER_WORD_SOLACE))
                {
                    utils.LogActivity("POWER_WORD_SOLACE", AttackTarget.SafeName);
                    return utils.Cast(POWER_WORD_SOLACE, AttackTarget);
                }

                if (talents.IsSelected(19) && ClarityOfWill()) return true;

                //Prayer of mending tank
                if (!Me.IsMoving && tank != null && tank.IsAlive && tank.Distance - tank.CombatReach - 1 <= 40 && tank.InLineOfSpellSight)
                {
                    if (DiscPriestSettings.Instance.Use_PoM && tank.HealthPercent <= DiscPriestSettings.Instance.PoM_HP
                        && ((tank.Guid != Me.Guid && DiscPriestSettings.Instance.RotationType != DiscPriestSettings.Rotation.PVP) || DiscPriestSettings.Instance.RotationType == DiscPriestSettings.Rotation.PVP)
                        && !utils.isMyAuraActive(PRAYER_OF_MENDING_BUFF, tank) && utils.AOEHealCount(tank,100,20f,DiscPriestSettings.Instance.HealNPC) >=2 && utils.CanCast(PRAYER_OF_MENDING))
                    {
                        utils.LogHealActivity(tank, " PRAYER_OF_MENDING", tank.SafeName);
                        return utils.Cast(PRAYER_OF_MENDING, tank);
                    }
                }
                //Prayer of mending off_tank
                if (!Me.IsMoving && off_tank != null && off_tank.IsAlive && off_tank.Distance - off_tank.CombatReach - 1 <= 40 && off_tank.InLineOfSpellSight)
                {
                    if (DiscPriestSettings.Instance.Use_PoM && off_tank.HealthPercent <= DiscPriestSettings.Instance.PoM_HP
                        && ((off_tank.Guid != Me.Guid && DiscPriestSettings.Instance.RotationType != DiscPriestSettings.Rotation.PVP) || DiscPriestSettings.Instance.RotationType == DiscPriestSettings.Rotation.PVP)
                        && !utils.isMyAuraActive(PRAYER_OF_MENDING_BUFF, off_tank) && utils.AOEHealCount(off_tank, 100, 20f, DiscPriestSettings.Instance.HealNPC) >= 2 && utils.CanCast(PRAYER_OF_MENDING))
                    {
                        utils.LogHealActivity(off_tank, " PRAYER_OF_MENDING", off_tank.SafeName);
                        return utils.Cast(PRAYER_OF_MENDING, off_tank);
                    }
                }
                //Prayer of mending player
                if (!Me.IsMoving && DiscPriestSettings.Instance.Use_PoM && !DiscPriestSettings.Instance.Use_PoM_Only_On_Tank && utils.CanCast(PRAYER_OF_MENDING))
                {
                    WoWUnit candidatePoM = utils.GetNeedMyAuraTarget("Prayer of Mending", 40f, DiscPriestSettings.Instance.HealNPC);
                    if (candidatePoM != null)
                    {
                        utils.LogActivity(" PRAYER_OF_MENDING: " + candidatePoM.SafeName);
                        return utils.Cast(PRAYER_OF_MENDING, candidatePoM);
                    }
                }

                //if (talents.IsSelected(19) && ClarityOfWill()) return true;


                if (ShiledSpam()) return true;
                if (!Me.IsMoving && !utils.IsGlobalCooldown() &&  !Me.IsCasting && hp <= HealPercent && utils.CanCast(HEAL))
                {
                    //Better use Surge of Light procs
                    if (utils.isAuraActive(SURGE_OF_LIGHT)
                        && utils.CanCast(FLASH_HEAL)
                        && (hp <= SoLPercent
                            || Me.GetAuraById(SURGE_OF_LIGHT).TimeLeft.TotalMilliseconds <= 3500
                            || utils.PlayerCountBuff(SURGE_OF_LIGHT) == 2))
                    {
                        utils.LogHealActivity(healTarget, FLASH_HEAL + " instead of heal for SoL proc", healTarget.SafeName);
                        return utils.Cast(FLASH_HEAL, healTarget);
                    }
                    if (!Me.IsMoving && !Me.IsCasting && !utils.IsGlobalCooldown())
                    {
                        utils.LogHealActivity(healTarget, " HEAL", healTarget.SafeName);
                        CurrentHealtarget = healTarget;
                        return utils.Cast(HEAL, healTarget);
                    }
                }
                
                
            }
            return false;
        }     

        private bool TankHealing()
        {
            if (tank != null && !tank.IsDead && tank.IsAlive && tank.Distance - tank.CombatReach - 1 <= 40 && utils.IsHealableByMe(tank) && tank.InLineOfSpellSight && tank.IsValid && !tank.Possessed && tank.VehicleInfo == null) 
            {
                if (tank.Combat && tank.HealthPercent <= DiscPriestSettings.Instance.TankShieldPercent /*&& !utils.isAuraActive(POWER_WORD_SHIELD, tank)*/
                    && (!utils.isAuraActive(WEAKENED_SOUL, tank) ) && utils.CanCast(POWER_WORD_SHIELD,tank))
                {
                    utils.LogHealActivity(tank, "TANK:  POWER_WORD_SHIELD", tank.SafeName);
                    return utils.Cast(POWER_WORD_SHIELD, tank);
                }

                if (tank.Combat && tank.HealthPercent <= DiscPriestSettings.Instance.PainSuppressionPercent && utils.CanCast(PAIN_SUPPRESSION,tank,true) && DiscPriestSettings.Instance.UsePainSuppression)
                {
                    utils.LogHealActivity(tank, "TANK:  PAIN_SUPPRESSION", tank.SafeName);
                    return utils.Cast(PAIN_SUPPRESSION, tank);
                }
                if (tank.HealthPercent <= FlashHealPercent && utils.CanCast(FLASH_HEAL) && !Me.IsMoving && utils.isAuraActive(WEAKENED_SOUL, tank))
                {
                    if(utils.GetSpellCooldown(PENANCE).TotalMilliseconds <= 2 * StyxWoW.WoWClient.Latency && (!Me.IsMoving || CanPenanceOnMoving))
                    {
                        utils.LogHealActivity(Me, "TANK:  PENANCE", tank.SafeName);
                        return utils.Cast(PENANCE, tank);
                    }
                    utils.LogHealActivity(tank, "TANK:  FLASH_HEAL", tank.SafeName);
                    CurrentHealtarget = tank;
                    return utils.Cast(FLASH_HEAL, tank);
                }
                /*if (tank.HealthPercent <= HealPercent && utils.CanCast(HEAL))
                {
                    //Better use Surge of Light procs
                    if (utils.isAuraActive(SURGE_OF_LIGHT)
                        && utils.CanCast(FLASH_HEAL)
                        && (tank.HealthPercent <= SoLPercent
                            || Me.GetAuraById(SURGE_OF_LIGHT).TimeLeft.TotalMilliseconds <= 3500
                            || utils.PlayerCountBuff(SURGE_OF_LIGHT) == 2))
                    {
                        utils.LogHealActivity(tank, FLASH_HEAL + "TANK:  instead of heal for SoL proc", tank.SafeName);
                        return utils.Cast(FLASH_HEAL, tank);
                    }
                    else if (!Me.IsMoving)
                    {
                        utils.LogHealActivity(tank, "TANK:  HEAL", tank.SafeName);
                        CurrentHealtarget = tank;
                        return utils.Cast(HEAL, tank);
                    }
                }*/

                
            }
            return false;
        }

        private bool OffTankHealing()
        {
            if (off_tank != null && !off_tank.IsDead && off_tank.IsAlive && off_tank.Distance - off_tank.CombatReach - 1 <= 40 && utils.IsHealableByMe(off_tank) && off_tank.InLineOfSpellSight && off_tank.IsValid && !off_tank.Possessed && off_tank.VehicleInfo == null)
            {
                if (off_tank.Combat && off_tank.HealthPercent <= DiscPriestSettings.Instance.OffTankShieldPercent /*&& !utils.isAuraActive(POWER_WORD_SHIELD, off_tank)*/
                    && (!utils.isAuraActive(WEAKENED_SOUL, off_tank)  ) && utils.CanCast(POWER_WORD_SHIELD,off_tank))
                {
                    utils.LogHealActivity(off_tank, "OFFTANK:  POWER_WORD_SHIELD", off_tank.SafeName);
                    return utils.Cast(POWER_WORD_SHIELD, off_tank);
                }

                if (off_tank.Combat && off_tank.HealthPercent <= DiscPriestSettings.Instance.PainSuppressionPercent && utils.CanCast(PAIN_SUPPRESSION, off_tank, true)
                    && DiscPriestSettings.Instance.UsePainSuppression && DiscPriestSettings.Instance.UsePainSuppressionOnOffTank)
                {
                    utils.LogHealActivity(off_tank, "OFFTANK:  PAIN_SUPPRESSION", off_tank.SafeName);
                    return utils.Cast(PAIN_SUPPRESSION, off_tank);
                }

                if (off_tank.HealthPercent <= FlashHealPercent && utils.CanCast(FLASH_HEAL) && !Me.IsMoving && utils.isAuraActive(WEAKENED_SOUL, off_tank))
                {
                    if (utils.GetSpellCooldown(PENANCE).TotalMilliseconds <= 2 * StyxWoW.WoWClient.Latency && (!Me.IsMoving || CanPenanceOnMoving))
                    {
                        utils.LogHealActivity(Me, "OFFTANK:  PENANCE", off_tank.SafeName);
                        return utils.Cast(PENANCE, off_tank);
                    }
                    utils.LogHealActivity(off_tank, "OFFTANK:  FLASH_HEAL", off_tank.SafeName);
                    CurrentHealtarget = off_tank;
                    return utils.Cast(FLASH_HEAL, off_tank);
                }
                /*if (off_tank.HealthPercent <= HealPercent && utils.CanCast(HEAL))
                {
                    //Better use Surge of Light procs
                    if (utils.isAuraActive(SURGE_OF_LIGHT)
                        && utils.CanCast(FLASH_HEAL)
                        && (off_tank.HealthPercent <= SoLPercent
                            || Me.GetAuraById(SURGE_OF_LIGHT).TimeLeft.TotalMilliseconds <= 3500
                            || utils.PlayerCountBuff(SURGE_OF_LIGHT) == 2))
                    {
                        utils.LogHealActivity(off_tank, FLASH_HEAL + "OFFTANK:  instead of heal for SoL proc", off_tank.SafeName);
                        return utils.Cast(FLASH_HEAL, off_tank);
                    }
                    else if (!Me.IsMoving)
                    {
                        utils.LogHealActivity(off_tank, "OFFTANK:  HEAL", off_tank.SafeName);
                        CurrentHealtarget = off_tank;
                        return utils.Cast(HEAL, off_tank);
                    }
                }*/
            }
            return false;
        }
      
        private bool Cleansing()
        {
            if (DiscPriestSettings.Instance.UsePurify || DiscPriestSettings.Instance.UseMassDispell)
            {
                WoWUnit player = null;
                if (utils.NeedsDispelPriest(Me, ExtraUtilsSettings.Instance.UseBossLogic))
                    player = Me;
                else if (tank != null && tank.IsAlive && tank.InLineOfSpellSight && tank.Distance - tank.CombatReach - 1 <= 40f && utils.IsHealableByMe(tank) && utils.NeedsDispelPriest(tank, ExtraUtilsSettings.Instance.UseBossLogic))
                    player = tank;
                else if (off_tank != null && off_tank.IsAlive && off_tank.InLineOfSpellSight && off_tank.Distance - off_tank.CombatReach - 1 <= 40f && utils.IsHealableByMe(off_tank) && utils.NeedsDispelPriest(off_tank, ExtraUtilsSettings.Instance.UseBossLogic))
                    player = off_tank;
                else
                    player = utils.GetDispelTargetPriest(40f, DiscPriestSettings.Instance.HealNPC, ExtraUtilsSettings.Instance.UseBossLogic);
                if (player != null)
                {
                    if (DiscPriestSettings.Instance.UseMassDispell && utils.MassDispelCountForPlayer(player, 15f, DiscPriestSettings.Instance.HealNPC) >= DiscPriestSettings.Instance.MassDispellCount && utils.CanCast(MASS_DISPEL)) 
                    {
                        utils.LogActivity("MASS_DISPEL", player.SafeName);
                        utils.Cast(MASS_DISPEL);
                        return SpellManager.ClickRemoteLocation(player.Location);
                    }

                    if (DiscPriestSettings.Instance.UsePurify && utils.CanCast(PURIFY))
                    {
                        utils.LogActivity("PURIFY", player.SafeName);
                        return utils.Cast(PURIFY, player);
                    }
                }
            }
            return false;
        }

        private bool Resurrect()
        {
            foreach (WoWPlayer player in utils.GetResurrectTargets(40f))
            {
                if (Blacklist.Contains(player.Guid, BlacklistFlags.All)) continue;
                else
                {
                    if (player.Distance > 40 || !player.InLineOfSpellSight) return false;
                    else if (utils.CanCast(RESURRECTION, player) && DiscPriestSettings.Instance.UseResurrection && !Me.IsMoving)
                    {
                        utils.LogActivity("RESURRECTION", player.Class.ToString());
                        Blacklist.Add(player, BlacklistFlags.All, new TimeSpan(0, 0, 60));
                        return utils.Cast(RESURRECTION, player);
                    }

                    return false;
                }
            }
            return false;
        }

        private bool Buff()
        {
            if (utils.Mounted() || IsCRPaused || !StyxWoW.IsInGame || !StyxWoW.IsInWorld
                || utils.IsEatingOrDrinking() )
                return false;

            /*if (DiscPriestSettings.Instance.RotationType == DiscPriestSettings.Rotation.PVP
                && !utils.isAuraActive(POWER_WORD_SHIELD) && (!utils.isAuraActive(WEAKENED_SOUL)  ) && utils.CanCast(POWER_WORD_SHIELD))
            {
                utils.LogHealActivity(Me, "POWER_WORD_SHIELD", Me.SafeName);
                return utils.Cast(POWER_WORD_SHIELD, Me);
            }*/

            if (DiscPriestSettings.Instance.AutoPWFortitude)
            {
                if ((!utils.isAuraActive(POWER_WORD_FORTITUDE) && !utils.isAuraActive(DARK_INTENT)) && utils.CanCast(POWER_WORD_FORTITUDE))
                {
                    utils.LogActivity("POWER_WORD_FORTITUDE");
                    return utils.Cast(POWER_WORD_FORTITUDE);
                }

                foreach (WoWPlayer player in Me.PartyMembers)
                {
                    if (player.Distance - player.CombatReach -1  > 40f || player.IsDead || player.IsGhost || !player.InLineOfSpellSight) continue;
                    else if ((!utils.isAuraActive(POWER_WORD_FORTITUDE, player) && !utils.isAuraActive(DARK_INTENT, player)) && utils.CanCast(POWER_WORD_FORTITUDE))
                    {
                        utils.LogActivity("POWER_WORD_FORTITUDE", player.SafeName);
                        return utils.Cast(POWER_WORD_FORTITUDE, player);
                    }
                }
            }
            if (CombatBuff())
                return true;
            return false;
        }

        private bool CombatBuff()
        {
            if (IsCRPaused)
                return false;
            if (DiscPriestSettings.Instance.UseFearWard && utils.CanCast(FEAR_WARD) && !utils.isAuraActive(FEAR_WARD))
            {
                utils.LogActivity("FEAR_WARD", Me.SafeName);
                return utils.Cast(FEAR_WARD, Me);
            }
            if (DiscPriestSettings.Instance.BurstSpeedMoving && Me.IsMoving && !Me.IsCasting && !Me.IsChanneling && !Me.Mounted && !Me.IsFalling
                && (Me.Combat || Me.MovementInfo.TimeMoved >= DiscPriestSettings.Instance.MoveTimeForSpeedBuff))
            {
                if (talents.IsSelected(5) && !utils.isAuraActive(ANGELIC_FEATHER_AURA))
                {
                    utils.LogActivity("moving....ANGELIC_FEATHER");
                    utils.Buff(ANGELIC_FEATHER);
                    SpellManager.ClickRemoteLocation(Me.Location);
                    Lua.DoString("SpellStopTargeting()");
                    return true;
                }
                if (talents.IsSelected(4) && !utils.isAuraActive(WEAKENED_SOUL, Me) /*&& !utils.isAuraActive(POWER_WORD_SHIELD, Me)*/ && utils.CanCast(POWER_WORD_SHIELD))
                {
                    utils.LogActivity("moving....POWER_WORD_SHIELD");
                    return utils.Cast(POWER_WORD_SHIELD, Me);
                }

            }

            return false;
        }
 
        private bool Dps()
        {
            if(DiscPriestSettings.Instance.RotationType == DiscPriestSettings.Rotation.PVP)
                AttackTarget = utils.getTargetPVPToAttack(RangeOfAttack, tank, DiscPriestSettings.Instance.AvoidCC);
            if (AttackTarget != null)
            {
                if (DiscPriestSettings.Instance.movementEnabled && (AttackTarget.Distance - AttackTarget.CombatReach - 1 > DiscPriestSettings.Instance.PullDistance || !AttackTarget.InLineOfSpellSight))
                    movement.KingHealMove(AttackTarget, DiscPriestSettings.Instance.PullDistance);

                if (!Me.IsMoving && (DiscPriestSettings.Instance.AutofaceTarget || SoloBotType))
                {
                    Me.SetFacing(AttackTarget);
                }

                if (DiscPriestSettings.Instance.UseMindSear && utils.AllAttaccableEnemyMobsInRangeFromTarget(AttackTarget, 10, ExtraUtilsSettings.Instance.provinGround_Targeting).Count() >= DiscPriestSettings.Instance.MindSearEnemyNumberMin)
                {
                    utils.LogActivity("MIND SEAR ",AttackTarget.SafeName);
                    //SetNextChannelMSSpellAllowed();
                    return utils.Cast(MIND_SEAR, AttackTarget);
                }

                if(DiscPriestSettings.Instance.UseSWP && utils.MyAuraTimeLeft(SHADOW_WORD_PAIN,AttackTarget) < 5400 && utils.CanCast(SHADOW_WORD_PAIN))
                {
                    utils.LogActivity("SHADOW_WORD_PAIN", AttackTarget.SafeName);
                    return utils.Cast(SHADOW_WORD_PAIN, AttackTarget);
                }
                if (!Me.IsChanneling && Me.Combat && Me.IsFacing(AttackTarget) && talents.IsSelected(9) && utils.CanCast(POWER_WORD_SOLACE))
                {
                    utils.LogActivity("POWER_WORD_SOLACE", AttackTarget.SafeName);
                    return utils.Cast(POWER_WORD_SOLACE, AttackTarget);
                }
                if (DiscPriestSettings.Instance.UsePenanceInDPS && utils.GetSpellCooldown(PENANCE).TotalMilliseconds <= 2 * StyxWoW.WoWClient.Latency && (!Me.IsMoving || CanPenanceOnMoving) )
                {
                    utils.LogActivity("PENANCE", AttackTarget.SafeName);
                    return utils.Cast(PENANCE, AttackTarget);
                }
                if (!Me.IsChanneling && Me.Combat && Me.IsFacing(AttackTarget) && !talents.IsSelected(9) && utils.CanCast(HOLY_FIRE, AttackTarget, true) /*&& !Me.IsMoving*/)
                {
                    utils.LogActivity("HOLY_FIRE", AttackTarget.SafeName);
                    return utils.Cast(HOLY_FIRE, AttackTarget);
                }
                
                Multidot();

                if (!Me.IsCasting && !Me.IsChanneling && !utils.IsGlobalCooldown() 
                    && utils.CanCast(HOLY_NOVA) && utils.AllAttaccableEnemyMobsInRange(12).Count() >= DiscPriestSettings.Instance.HolyNovaEnemiesNumber)
                {
                    utils.LogActivity("HOLY_NOVA");
                    return utils.Cast(HOLY_NOVA);
                }

                if (!Me.IsCasting && !Me.IsChanneling && !utils.IsGlobalCooldown() && utils.CanCast(SMITE, AttackTarget) && !Me.IsMoving)
                {
                    utils.LogActivity("SMITE", AttackTarget.SafeName);
                    return utils.Cast(SMITE, AttackTarget);
                }
            }
            if (DiscPriestSettings.Instance.movementEnabled && Me.CurrentTarget != null && !Me.CurrentTarget.IsDead && (!Me.CurrentTarget.InLineOfSpellSight || Me.CurrentTarget.Distance - Me.CurrentTarget.CombatReach - 1 > DiscPriestSettings.Instance.PullDistance))
            {
                movement.KingHealMove(Me.CurrentTarget, DiscPriestSettings.Instance.PullDistance);
            }
            
            
            return false;          
        }

        private bool DpsHelp()
        {
            if (DiscPriestSettings.Instance.RotationType == DiscPriestSettings.Rotation.PVP)
                AttackTarget = utils.getTargetPVPToAttack(RangeOfAttack, tank, DiscPriestSettings.Instance.AvoidCC);
            if (AttackTarget != null)
            {
                if (DiscPriestSettings.Instance.movementEnabled && (AttackTarget.Distance - AttackTarget.CombatReach - 1 > DiscPriestSettings.Instance.PullDistance || !AttackTarget.InLineOfSpellSight))
                    movement.KingHealMove(AttackTarget, DiscPriestSettings.Instance.PullDistance);

                if (!Me.IsMoving && (DiscPriestSettings.Instance.AutofaceTarget || SoloBotType))
                {
                    Me.SetFacing(AttackTarget);
                }

                if (DiscPriestSettings.Instance.UseMindSear && utils.AllAttaccableEnemyMobsInRangeFromTarget(AttackTarget, 10, ExtraUtilsSettings.Instance.provinGround_Targeting).Count() >= DiscPriestSettings.Instance.MindSearEnemyNumberMin)
                {
                    utils.LogActivity("MIND SEAR ", AttackTarget.SafeName);
                    //SetNextChannelMSSpellAllowed();
                    return utils.Cast(MIND_SEAR, AttackTarget);
                }

                if (DiscPriestSettings.Instance.UseSWP && utils.MyAuraTimeLeft(SHADOW_WORD_PAIN, AttackTarget) < 5400 && utils.CanCast(SHADOW_WORD_PAIN))
                {
                    utils.LogActivity("SHADOW_WORD_PAIN", AttackTarget.SafeName);
                    return utils.Cast(SHADOW_WORD_PAIN, AttackTarget);
                }
                if (!Me.IsChanneling && Me.Combat && Me.IsFacing(AttackTarget) && talents.IsSelected(9) && utils.CanCast(POWER_WORD_SOLACE))
                {
                    utils.LogActivity("POWER_WORD_SOLACE", AttackTarget.SafeName);
                    return utils.Cast(POWER_WORD_SOLACE, AttackTarget);
                }
                if (DiscPriestSettings.Instance.UsePenanceInDPS && utils.GetSpellCooldown(PENANCE).TotalMilliseconds <= 2 * StyxWoW.WoWClient.Latency && (!Me.IsMoving || CanPenanceOnMoving))
                {
                    utils.LogActivity("PENANCE", AttackTarget.SafeName);
                    return utils.Cast(PENANCE, AttackTarget);
                }
                if (!Me.IsChanneling && Me.Combat && Me.IsFacing(AttackTarget) && !talents.IsSelected(9) && utils.CanCast(HOLY_FIRE, AttackTarget, true) /*&& !Me.IsMoving*/)
                {
                    utils.LogActivity("HOLY_FIRE", AttackTarget.SafeName);
                    return utils.Cast(HOLY_FIRE, AttackTarget);
                }

                Multidot();

                if (!Me.IsCasting && !Me.IsChanneling && !utils.IsGlobalCooldown()
                    && utils.CanCast(HOLY_NOVA) && utils.AllAttaccableEnemyMobsInRange(12).Count() >= DiscPriestSettings.Instance.HolyNovaEnemiesNumber)
                {
                    utils.LogActivity("HOLY_NOVA");
                    return utils.Cast(HOLY_NOVA);
                }

            }
            else if (DiscPriestSettings.Instance.movementEnabled && Me.CurrentTarget != null && !Me.CurrentTarget.IsDead && (!Me.CurrentTarget.InLineOfSpellSight || Me.CurrentTarget.Distance - Me.CurrentTarget.CombatReach - 1 > DiscPriestSettings.Instance.PullDistance))
            {
                movement.KingHealMove(Me.CurrentTarget, DiscPriestSettings.Instance.PullDistance);
            }

            return false;
        }

        private bool ProcWork()
        {
            //Surge of Light
            if (utils.isAuraActive(SURGE_OF_LIGHT))
            {
                if (healTarget != null)
                {                
                    //Surge of Light
                    if (utils.CanCast(FLASH_HEAL) && (healTarget.HealthPercent <= SoLPercent
                                                        || Me.GetAuraById(SURGE_OF_LIGHT).TimeLeft.TotalMilliseconds <= 3500
                                                        || utils.PlayerCountBuff(SURGE_OF_LIGHT) == 2))
                    {
                        utils.LogActivity("SoL Proc:FLASH_HEAL ", healTarget.SafeName);
                        return utils.Cast(FLASH_HEAL, healTarget);
                    }
                  
                }
            }

            if (DiscPriestSettings.Instance.POH_always_with_T17_and_Archangel && utils.isAuraActive(T17_CLEAR_THOUGHTS_BUFF) && utils.isAuraActive("Empowered Archangel")
                && !Me.IsMoving && !Me.IsCasting && !utils.IsGlobalCooldown())
            {
                WoWUnit poh_target = null;
                poh_target = utils.BestPoHTarget(100, 3, DiscPriestSettings.Instance.HealNPC);
                if (poh_target != null)
                {
                    utils.LogActivity("T17 + ARCHANGEL PROC BONUS: PRAYER_OF_HEALING", poh_target.SafeName);
                    return utils.Cast(PRAYER_OF_HEALING, poh_target);
                }
            }

            //T17_CLEAR_THOUGHTS_BUFF
            if (utils.isAuraActive(T17_CLEAR_THOUGHTS_BUFF) && !Me.IsCasting && !utils.IsGlobalCooldown())
            {
                if (utils.CanCast(PRAYER_OF_HEALING) && !Me.IsMoving)
                {
                    WoWUnit poh_target = null;
                    poh_target = utils.BestPoHTarget(DiscPriestSettings.Instance.T17PrayerOfHealingPercent, DiscPriestSettings.Instance.T17PrayerOfHealingNumber/*, true*/, DiscPriestSettings.Instance.HealNPC);
                    if (poh_target != null)
                    {
                        utils.LogActivity("T17 PROC BONUS: PRAYER_OF_HEALING", poh_target.SafeName);
                        return utils.Cast(PRAYER_OF_HEALING, poh_target);
                    }
                }
            }
            if (utils.isAuraActive("Empowered Archangel") && !Me.IsCasting && !utils.IsGlobalCooldown())
            {
                if (utils.CanCast(PRAYER_OF_HEALING) && !Me.IsMoving)
                {
                    WoWUnit poh_target = null;
                    poh_target = utils.BestPoHTarget(DiscPriestSettings.Instance.ArchangelPrayerOfHealingPercent, DiscPriestSettings.Instance.ArchangelPrayerOfHealingNumber/*, true*/, DiscPriestSettings.Instance.HealNPC);
                    if (poh_target != null)
                    {
                        utils.LogActivity("EMPOWERED ARCHANGEL PROC BONUS: PRAYER_OF_HEALING", poh_target.SafeName);
                        return utils.Cast(PRAYER_OF_HEALING, poh_target);
                    }
                }
            }
            
            return false;
        }
       
        private bool SpiritShell_detected()
        {
            if (Me.ActiveAuras.Any(x => x.Value.SpellId == SPIRIT_SHELL))
            {
                WoWUnit candidatePoHForSpiritShell = Me;
                /*foreach (var woWPartyMember in utils.GetGroupMembers())
                {
                    if (currentGroupForSS >= 8)
                        currentGroupForSS = 0;
                    if (woWPartyMember.ToPlayer() != null)
                    {
                        if (woWPartyMember.GroupNumber == currentGroupForSS && !Me.IsMoving && !utils.MeIsChanneling && !Me.IsCasting
                            && utils.CanCast(PRAYER_OF_HEALING, woWPartyMember.ToPlayer(),true)
                            && woWPartyMember.ToPlayer().Distance - woWPartyMember.ToPlayer().CombatReach -1  <= 30
                            && woWPartyMember.ToPlayer().InLineOfSpellSight
                            && woWPartyMember.ToPlayer().IsAlive)
                        {
                            utils.LogActivity("SPIRIT_SHELL BUFFED casting Prayer of Healing on player of group:" + (woWPartyMember.GroupNumber + 1).ToString() + "   " + woWPartyMember.ToPlayer().SafeName);
                            utils.Cast(PRAYER_OF_HEALING, woWPartyMember.ToPlayer());
                            currentGroupForSS = currentGroupForSS + 1;
                            return true;
                        }
                    }

                }
                currentGroupForSS = currentGroupForSS + 1;
                return true;*/
                if (Me.CurrentTarget != null && (Me.CurrentTarget.ToPlayer().IsInMyPartyOrRaid || Me.CurrentTarget.IsMe) 
                    && Me.CurrentTarget.Distance-1<=40f &&Me.CurrentTarget.InLineOfSpellSight)
                {
                    candidatePoHForSpiritShell = Me.CurrentTarget;
                }
                utils.LogActivity("SPIRIT_SHELL BUFFED casting Prayer of Healing on Current Target: " + candidatePoHForSpiritShell.SafeName);
                return utils.Cast(PRAYER_OF_HEALING, candidatePoHForSpiritShell);
            }
            /*else
                currentGroupForSS = 0;*/
            return false;
        }

        private bool CC()
        {
            if (utils.CanCast(PSYCHIC_SCREAM) && DiscPriestSettings.Instance.UsePsychicScream && Me.Combat && (utils.AllAttaccableEnemyMobsInRange(8).Count() >= 1))
            {
                utils.LogActivity("PSYCHIC_SCREAM");
                return utils.Cast(PSYCHIC_SCREAM);
            }
            if ( utils.CanCast(VOID_TENDRILS) && DiscPriestSettings.Instance.UseVoidTendrils && Me.Combat && (utils.AllAttaccableEnemyMobsInRange(8).Count() >= 1))
            {
                utils.LogActivity("VOID_TENDRILS");
                return utils.Cast(VOID_TENDRILS);
            }
            if (utils.CanCast(PSYFIEND) && DiscPriestSettings.Instance.UsePsyfiend && Me.Combat && (utils.AllAttaccableEnemyMobsInRange(20).Count() >= 1))
            {
                utils.LogActivity("PSYFIEND");
                utils.Cast(PSYFIEND);
                return SpellManager.ClickRemoteLocation(Me.Location);
            }

            return false;
        }

        private bool DispellMagic()
        {
            if (DiscPriestSettings.Instance.UseDispellMagic && Me.CurrentTarget != null && Me.CurrentTarget.Attackable && Me.CurrentTarget.IsAlive
                && utils.CanCast(DISPELL_MAGIC,Me.CurrentTarget,true))
            {
                if (utils.EnemyNeedDispellASAP(Me.CurrentTarget))
                {
                    utils.LogActivity("DISPELL_MAGIC", Me.CurrentTarget.SafeName);
                    return utils.Cast(DISPELL_MAGIC, Me.CurrentTarget);
                }
            }
            return false;
        }

        public bool OnlyInstantSpellRotation()
        {
            
            while (ProcWork()) return true;
            extra.UseHealPotion_Healthstone();
            while (extra.UseRacials()) return true;
            while (extra.UseTrinket1()) return true;
            while (extra.UseTrinket2()) return true;
            while (extra.UseManaItem()) return true;
            if (DiscPriestSettings.Instance.PriorizedTargettedSelectivePW_Shield && ShiledSpam()) return true;
            
            //PURIFY
            if (DiscPriestSettings.Instance.UsePurify)
            {
                WoWUnit player = utils.GetDispelTargetPriest(40f,false,ExtraUtilsSettings.Instance.UseBossLogic);

                if (player != null)
                {
                    if (DiscPriestSettings.Instance.UsePurify && utils.CanCast(PURIFY))
                    {
                        utils.LogActivity("PURIFY", player.SafeName);
                        return utils.Cast(PURIFY, player);
                    }
                }
            }
            
            //AOE
            if (Me.Combat && utils.CanCast(POWER_WORD_BARRIER) && DiscPriestSettings.Instance.AutoUsePWBarrier)
            {
                WoWUnit pwb_target = utils.BestPWBTargetLocation(DiscPriestSettings.Instance.PWBarrierPercent, DiscPriestSettings.Instance.PWBarrierNumber);
                if (pwb_target != null)
                {
                    utils.LogActivity("POWER_WORD_BARRIER", pwb_target.SafeName);
                    utils.Cast(POWER_WORD_BARRIER);
                    return SpellManager.ClickRemoteLocation(pwb_target.Location);
                }
            }

            if (!DiscPriestSettings.Instance.DisableAOE_HealingRotation)
            {
                //divine star
                if (!Me.IsMoving && utils.CanCast(DIVINE_STAR))
                {
                    WoWUnit ds_target = utils.BestDSTarget(DiscPriestSettings.Instance.CascadeHaloDivinestarPercent, DiscPriestSettings.Instance.CascadeHaloDivineStarNumber);
                    if (ds_target != null && utils.CanCast(DIVINE_STAR, ds_target, true))
                    {
                        ds_target.Face();
                        utils.LogActivity("DIVINE_STAR", ds_target.SafeName);
                        return utils.Cast(DIVINE_STAR, ds_target);
                    }
                }

                if (!Me.IsCasting && !Me.IsChanneling && !utils.IsGlobalCooldown() && utils.CanCast(HOLY_NOVA)
                    && utils.GetMemberCountBelowThresholdInRangeFromPlayer(DiscPriestSettings.Instance.HolyNovaPercent, Me, 12, DiscPriestSettings.Instance.HealNPC) >= DiscPriestSettings.Instance.HolyNovaNumber)
                {
                    utils.LogActivity("HOLY_NOVA");
                    return utils.Cast(HOLY_NOVA);
                }
            }
            if (ShiledSpam()) return true;
            //Atonement heal
            if (AttackTarget != null)
            {
                if (!Me.IsMoving && (DiscPriestSettings.Instance.AutofaceTarget || SoloBotType))
                {
                    Me.SetFacing(AttackTarget);
                }
                if (!Me.IsChanneling && Me.Combat && Me.IsFacing(AttackTarget) && talents.IsSelected(9) && utils.CanCast(POWER_WORD_SOLACE))
                {
                    utils.LogActivity("POWER_WORD_SOLACE", AttackTarget.SafeName);
                    return utils.Cast(POWER_WORD_SOLACE, AttackTarget);
                }
                if (!Me.IsChanneling && Me.Combat && Me.IsFacing(AttackTarget) && !talents.IsSelected(9) && utils.CanCast(HOLY_FIRE, AttackTarget, true))
                {
                    utils.LogActivity("HOLY_FIRE", AttackTarget.SafeName);
                    return utils.Cast(HOLY_FIRE, AttackTarget);
                }
            }

            if (healTarget != null)
            {
                double hp = healTarget.HealthPercent;

                if (healTarget.Distance - healTarget.CombatReach - 1 > 40 || !healTarget.InLineOfSpellSight)
                {
                    return false;
                }
                else
                {
                    //SAVING GRACE
                    if (utils.CanCast(SAVING_GRACE) && healTarget.HealthPercent <= DiscPriestSettings.Instance.SavingGraceHP
                            && utils.PlayerCountBuff(SAVING_GRACE) <= DiscPriestSettings.Instance.SavinGraceDebuffStackNumber)
                    {
                        utils.LogHealActivity(healTarget, "SAVING GRACE", healTarget.SafeName);
                        return utils.Cast(SAVING_GRACE, healTarget);
                    }
                    //Surge of Light
                    if (utils.isAuraActive(SURGE_OF_LIGHT)
                            && (hp <= SoLPercent
                                || Me.GetAuraById(SURGE_OF_LIGHT).TimeLeft.TotalMilliseconds <= 3500
                                || utils.PlayerCountBuff(SURGE_OF_LIGHT) == 2))
                    {
                        utils.LogHealActivity(healTarget, " FLASH_HEAL", healTarget.SafeName);
                        return utils.Cast(FLASH_HEAL, healTarget);
                    }
                    if (hp <= HealPercent)
                    {
                        //Better use Surge of Light procs
                        if (utils.isAuraActive(SURGE_OF_LIGHT)
                            && (hp <= SoLPercent
                                || Me.GetAuraById(SURGE_OF_LIGHT).TimeLeft.TotalMilliseconds <= 3500
                                || utils.PlayerCountBuff(SURGE_OF_LIGHT) == 2))
                        {
                            utils.LogHealActivity(healTarget, FLASH_HEAL + " instead of heal for SoL proc", healTarget.SafeName);
                            return utils.Cast(FLASH_HEAL, healTarget);
                        }
                    }

                    if (!DiscPriestSettings.Instance.UsePainSuppressionOnlyOnTank && hp <= DiscPriestSettings.Instance.PainSuppressionPercent && utils.CanCast(PAIN_SUPPRESSION) && DiscPriestSettings.Instance.UsePainSuppression)
                    {
                        utils.LogHealActivity(healTarget, " PAIN_SUPPRESSION", healTarget.SafeName);
                        return utils.Cast(PAIN_SUPPRESSION, healTarget);
                    }
                    if (/*!utils.isAuraActive(POWER_WORD_SHIELD, healTarget) &&*/ (!utils.isAuraActive(WEAKENED_SOUL, healTarget) ) && utils.CanCast(POWER_WORD_SHIELD, healTarget))
                    {
                        utils.LogHealActivity(healTarget, " POWER_WORD_SHIELD", healTarget.SafeName);
                        return utils.Cast(POWER_WORD_SHIELD, healTarget);
                    }
                }
            }
            return false;
        }

        public bool ShiledSpam()
        {
            if (Blanket_PWS && !Me.IsCasting && !utils.IsGlobalCooldown())
            {
                WoWUnit candidatePwS = null;
                if (DiscPriestSettings.Instance.TargettedSelectivePW_Shield)
                {
                    if (Me.CurrentTarget != null && (!Me.CurrentTarget.Attackable && Me.CurrentTarget.IsFriendly && Me.CurrentTarget.ToPlayer()!=null && Me.CurrentTarget.ToPlayer().IsInMyPartyOrRaid || Me.CurrentTarget.IsMe))
                    {
                        foreach (var woWPartyMember in utils.GetGroupMembers())
                        {
                            if (woWPartyMember.ToPlayer() != null && woWPartyMember.ToPlayer().Guid == Me.CurrentTarget.Guid)
                            {
                                if (SelectedGroupNumber != (int)woWPartyMember.GroupNumber)
                                {
                                    utils.LogActivity("New PWS group selectd: " + (int)woWPartyMember.GroupNumber);
                                }
                                SelectedGroupNumber = (int)woWPartyMember.GroupNumber;

                            }
                        }
                    }
                    candidatePwS = utils.GetTargetToShield(40f, DiscPriestSettings.Instance.HealNPC, SelectedGroupNumber);
                }
                else
                    candidatePwS = utils.GetTargetToShield(40f, DiscPriestSettings.Instance.HealNPC, -1);
                if (candidatePwS != null)
                {
                    utils.LogActivity("SPAM  POWER_WORD_SHIELD: " + candidatePwS.SafeName);
                    return utils.Cast(POWER_WORD_SHIELD, candidatePwS);
                }
            }
            return false;
        }

        public bool CombatRotation()
        {
            while (ProcWork()) return true;
            extra.UseHealPotion_Healthstone();
            if (HotkeyHandle()) return true;
            while (extra.UseRacials()) return true;
            while (extra.UseTrinket1()) return true;
            while (extra.UseTrinket2()) return true;
            while (extra.UseManaItem()) return true;
            if (DiscPriestSettings.Instance.PriorizedTargettedSelectivePW_Shield && ShiledSpam()) return true;
            CC();

            if ((SoloBotType || DiscPriestSettings.Instance.movementEnabled) && Me.CurrentTarget != null && Me.IsMoving && Me.CurrentTarget.InLineOfSpellSight && Me.CurrentTarget.Distance - Me.CurrentTarget.CombatReach - 1 <= DiscPriestSettings.Instance.PullDistance)
            {
                Navigator.PlayerMover.MoveStop();
            }

            if (DiscPriestSettings.Instance.RotationType == DiscPriestSettings.Rotation.PVE)
            {
                while (Self()) return true;
                while (ManaRegen()) return true;
                while (Cleansing()) return true;
                if (DiscPriestSettings.Instance.PriorizeTankHealing)
                    while(TankHealing()) return true;
                while (AoE()) return true;
                if (!DiscPriestSettings.Instance.PriorizeTankHealing)
                    while (TankHealing()) return true;
                if (DiscPriestSettings.Instance.OffTankHealing)
                    while (OffTankHealing()) return true;
                while (Interrupt()) return true;
                while (Healing()) return true;
                if (UsingAtonementHealing && Me.ManaPercent >= DiscPriestSettings.Instance.AtonementManaThreshold)
                {
                    if(Atonement()) return true;
                }
                /*if (DiscPriestSettings.Instance.HelpDPS)
                    DpsHelp();
                return false;*/
            }
            else if (DiscPriestSettings.Instance.RotationType == DiscPriestSettings.Rotation.PVP)
            {
                while (Self()) return true;
                while (ManaRegen()) return true;
                while (Cleansing()) return true;
                if (DiscPriestSettings.Instance.PriorizeTankHealing)
                    while (TankHealing()) return true;                
                DispellMagic();
                while (AoE()) return true;
                if (!DiscPriestSettings.Instance.PriorizeTankHealing)
                    while (TankHealing()) return true;
                if (DiscPriestSettings.Instance.OffTankHealing)
                    while (OffTankHealing()) return true;
                while (Interrupt()) return true;
                while (Healing()) return true;               
                if (UsingAtonementHealing /*&& DiscPriestSettings.Instance.UseAtonement*/ && Me.ManaPercent >= DiscPriestSettings.Instance.AtonementManaThreshold)
                {
                    Dps();
                }
                return false;
            }

            else if (DiscPriestSettings.Instance.RotationType == DiscPriestSettings.Rotation.QUESTING)
            {
                while (Self()) return true;
                while (ManaRegen()) return true;
                while (Cleansing()) return true;
                while (Interrupt()) return true;
                SoloHealing();
                Dps();
                return false;
            }
            else
                utils.LogActivity("NO VALID ROTATION ");
            return false;

        }

        public void StopCastingCheck()
        {
            //Stop Casting Healing Spells
            if (Me.CastingSpell != null &&
                (Me.CurrentCastId == FLASH_HEAL || Me.CurrentCastId == HEAL))
            {
                if (CurrentHealtarget != null && !CurrentHealtarget.IsAlive)
                {
                    CurrentHealtarget = null;
                    SpellManager.StopCasting();
                    Logging.Write(DateTime.Now.ToString("ss:fff ") + "Stop Casting: Unit is Dead");
                }

                else if (CurrentHealtarget != null && CurrentHealtarget.IsAlive && !CurrentHealtarget.InLineOfSpellSight)
                {
                    CurrentHealtarget = null;
                    SpellManager.StopCasting();
                    Logging.Write(DateTime.Now.ToString("ss:fff ") + "Stop Casting: Unit not In Line of Spell Sight");
                }

                else if (CurrentHealtarget != null && CurrentHealtarget.IsAlive && CurrentHealtarget.Distance - CurrentHealtarget.CombatReach -1  > 40f)
                {
                    CurrentHealtarget = null;
                    SpellManager.StopCasting();
                    Logging.Write(DateTime.Now.ToString("ss:fff ") + "Stop Casting: Unit out of range");
                }

                else if (CurrentHealtarget != null && CurrentHealtarget.IsAlive &&
                        CurrentHealtarget.HealthPercent > 99)
                {
                    CurrentHealtarget = null;
                    SpellManager.StopCasting();
                    Logging.Write(DateTime.Now.ToString("ss:fff ") + "Stop Casting: Unit Full HP");
                }        
            }
        }

        public bool SoS()
        {
            //priorize me if under sos percentage:
            //if (Me.HealthPercent <= DiscPriestSettings.Instance.SoSPercent)
            //    healTarget = Me;

            if(healTarget!=null && healTarget.HealthPercent <= DiscPriestSettings.Instance.SoSPercent )
            {
                if (utils.CanCast(SAVING_GRACE) && healTarget.HealthPercent <= DiscPriestSettings.Instance.SavingGraceHP
                    && utils.PlayerCountBuff(SAVING_GRACE) <= DiscPriestSettings.Instance.SavinGraceDebuffStackNumber)
                {
                    utils.LogHealActivity(healTarget, "SOS:   SAVING GRACE", healTarget.SafeName);
                    return utils.Cast(SAVING_GRACE, healTarget);
                }
                if (/*!utils.isAuraActive(POWER_WORD_SHIELD, healTarget) &&*/
                    !utils.isAuraActive(WEAKENED_SOUL, healTarget)
                    && utils.CanCast(POWER_WORD_SHIELD, healTarget))
                {
                    utils.LogHealActivity(healTarget, "SOS: POWER_WORD_SHIELD", healTarget.SafeName);
                    return utils.Cast(POWER_WORD_SHIELD, healTarget);
                }
                if (utils.GetSpellCooldown(PENANCE).TotalMilliseconds <= 2 * StyxWoW.WoWClient.Latency && (!Me.IsMoving || CanPenanceOnMoving))
                {
                    CurrentHealtarget = healTarget;
                    utils.LogHealActivity(healTarget, "SOS:   PENANCE", healTarget.SafeName);
                    return utils.Cast(PENANCE, healTarget);
                }
                if (utils.isAuraActive(SURGE_OF_LIGHT))
                {
                    utils.LogHealActivity(healTarget, "SOS:   SURGE_OF_LIGHT::FLASH_HEAL", healTarget.SafeName);
                    CurrentHealtarget = healTarget;
                    return utils.Cast(FLASH_HEAL, healTarget);
                }                
                if (!Me.IsMoving && utils.GetSpellCooldown(PENANCE).TotalMilliseconds > 2 * StyxWoW.WoWClient.Latency && utils.CanCast(FLASH_HEAL))
                {
                    utils.LogHealActivity(healTarget, "SOS:   FLASH_HEAL", healTarget.SafeName);
                    CurrentHealtarget = healTarget;
                    return utils.Cast(FLASH_HEAL, healTarget);
                }
           
            }
            return false;
        }

        private bool Multidot()
        {
            if (DiscPriestSettings.Instance.MultidotEnabled)
            {
                int enemyNumber = utils.AllAttaccableEnemyMobsInRangeTargettingMyParty(40f, DiscPriestSettings.Instance.MultidotAvoidCC).Count();
                if (enemyNumber >= DiscPriestSettings.Instance.Multidot_SW_Pain_EnemyNumberMin
                    /*|| enemyNumber >= DiscPriestSettings.Instance.Multidot_VampiricTouch_EnemyNumberMin*/)
                {
                    WoWUnit TargetForMultidot = null;
                    //apply  ShadowWord:Pain and always refresh it right before the last tick;
                    if (/*utils.CanCast(SHADOW_WORD_PAIN) &&*/ utils.AllEnemyMobsHasMyAura(SHADOW_WORD_PAIN).Count() < DiscPriestSettings.Instance.Multidot_SW_Pain_EnemyNumberMax)
                    {
                        TargetForMultidot = utils.NextApplyAuraTarget(SHADOW_WORD_PAIN_STRING, 40, 1500, DiscPriestSettings.Instance.MultidotAvoidCC);
                        if (TargetForMultidot != null)
                        {
                            utils.LogActivity("   MULTIDOT SHADOW_WORD_PAIN  ", TargetForMultidot.SafeName);
                            return utils.Cast(SHADOW_WORD_PAIN, TargetForMultidot);
                        }
                    }
                }
            }
            return false;
        }

        private DateTime nextTimeNormalRotationallowed = DateTime.Now;

        public void SetNextTimeNormalRotation(int time)
        {
            nextTimeNormalRotationallowed = DateTime.Now + new TimeSpan(0, 0, 0, 0, time);
        }

        private void SetAtonementAndNormalHealing()
        {
            if (DiscPriestSettings.Instance.AutoSwitchAtonementNormal)
            {
                if (AttackTarget != null && ((!utils.isAuraActive(ARCHANGEL, Me) && utils.PlayerCountBuff(EVANGELISM) < 5) || !DiscPriestSettings.Instance.AtonementOnlyForArchangel))
                {
                    if (!UsingAtonementHealing)
                    {
                        if (DiscPriestSettings.Instance.ShowMessageSwitching)
                            Lua.DoString(@"print('AUTOSWITCH: Atonement Healing \124cFF15E61C ENABLED!')");
                        UsingAtonementHealing = true;
                        SetAtonementVariables();
                    }
                }
                else if (AttackTarget == null || ((utils.isAuraActive(ARCHANGEL, Me) || utils.PlayerCountBuff(EVANGELISM) == 5) && DiscPriestSettings.Instance.AtonementOnlyForArchangel))
                {
                    if (UsingAtonementHealing)
                    {
                        if (DiscPriestSettings.Instance.ShowMessageSwitching)
                            Lua.DoString(@"print('AUTOSWITCH: Atonement healing \124cFFE61515 DISABLED!')");
                        UsingAtonementHealing = false;
                        SetNoAtonementVariables();
                    }
                }

            }
            else
            {
                if (DiscPriestSettings.Instance.UseDisciplineAtonementHealingRotation)
                {
                    if (!UsingAtonementHealing)
                    {
                        UsingAtonementHealing = true;
                        SetAtonementVariables();
                    }
                }
                else
                {
                    if (UsingAtonementHealing)
                    {
                        UsingAtonementHealing = false;
                        SetNoAtonementVariables();
                    }
                }
            }
        }
        
        public override bool Combat
        {
            get
            {
                if (DiscPriestSettings.Instance.TrySaveMana)
                    StopCastingCheck();
                if ((Me.Mounted && !DiscPriestSettings.Instance.AutoDismountOnCombat)
                    || IsCRPaused /*|| utils.MeIsChanneling*/ || !StyxWoW.IsInGame || !StyxWoW.IsInWorld || Me.Silenced
                    || (!ExtraUtilsSettings.Instance.FastRotation && (utils.IsGlobalCooldown() || Me.IsCasting))
                    || utils.IsEatingOrDrinking() )
                    return false;
                SetAtonementAndNormalHealing();

                //UPDATE TANK
                //tank = utils.GetTank();
                tank = utils.SimpleGetTank(40f);
                if (tank == null || !tank.IsValid || !tank.IsAlive) tank = Me;

                if (tank != null && (lastTank == null || lastTank.Guid != tank.Guid))
                {
                    lastTank = tank;
                    utils.LogActivity(TANK_CHANGE, tank.SafeName);
                }
                off_tank = utils.SimpleGetOffTank(40f, tank);
                if (off_tank != null && (lastOffTank == null || lastOffTank.Guid != off_tank.Guid))
                {
                    lastOffTank = off_tank;
                    utils.LogActivity(OFF_TANK_CHANGE, off_tank.SafeName);
                }

                healTarget = utils.GetHealTarget(40f, DiscPriestSettings.Instance.HealNPC);
                AttackTarget = utils.getTargetToAttack(RangeOfAttack, tank, DiscPriestSettings.Instance.AvoidCC, ExtraUtilsSettings.Instance.UseBossLogic);

                if (!IsCRPaused)
                {
                    if (ExtraUtilsSettings.Instance.UseBossLogic)
                    {
                        int time = 0;
                        time = utils.SpecificEncounterNeedStopCast();
                        if (time == 0)
                            time = utils.SpecificEncounterDontCast();
                        if (time > 0)
                        {
                            SpellManager.StopCasting();
                            utils.LogActivity("STOP CASTING/CHANNELING");
                            SetNextTimeNormalRotation(time);
                        }
                        if (nextTimeNormalRotationallowed > DateTime.Now)
                            return OnlyInstantSpellRotation();
                    }
                    while (SpiritShell_detected()) return true;
                    while (DiscPriestSettings.Instance.SoSEnabled && SoS()) return true;
                    if (!utils.MeIsChanneling)
                    {
                        if (DiscPriestSettings.Instance.PriorizeTankHealing && TankHealing() && OffTankHealing())
                            return true;

                        if (CombatBuff()) return true;
                        if (!Me.ActiveAuras.Any(x => x.Value.SpellId == SPIRIT_SHELL))
                            return CombatRotation();
                    }
                }
                return false;
            }
        }

        HealInterruptDispellsCleanse_Manager Disc_healInterrDispClea_Manager = new HealInterruptDispellsCleanse_Manager();
        public bool ClarityOfWill(bool ignoreHP=false)
        {
            if (!Me.IsMoving && !Me.IsCasting /*&& !utils.IsGlobalCooldown()*/ && utils.CanCast(CLARITY_OF_WILL) && DiscPriestSettings.Instance.UseClarityOfWill && Me.ManaPercent >= DiscPriestSettings.Instance.ClarityOfWillMana)
            {
                //tank first
                bool tank_need_clarity = (tank != null && (tank.Guid != Me.Guid || DiscPriestSettings.Instance.RotationType == DiscPriestSettings.Rotation.PVP) && tank.Distance - tank.CombatReach - 1 <= 40 && tank.InLineOfSpellSight && utils.MyAuraTimeLeft(CLARITY_OF_WILL, tank) <= 8000
                    && (tank.HealthPercent <= DiscPriestSettings.Instance.ClarityOfWillTanksHP || ignoreHP) && tank.IsValid && !tank.Possessed && tank.VehicleInfo == null);
                bool off_tank_need_clarity = (off_tank != null && off_tank.Guid != Me.Guid && off_tank.Distance - off_tank.CombatReach - 1 <= 40 && off_tank.InLineOfSpellSight && utils.MyAuraTimeLeft(CLARITY_OF_WILL,off_tank) <= 8000
                    && (tank.HealthPercent <= DiscPriestSettings.Instance.ClarityOfWillTanksHP || ignoreHP) && off_tank.IsValid && !off_tank.Possessed && off_tank.VehicleInfo == null);
                WoWUnit tank_to_clarity = null;
                if( (tank_need_clarity && !off_tank_need_clarity) || (tank_need_clarity && off_tank_need_clarity && tank.HealthPercent <= off_tank.HealthPercent) )
                    tank_to_clarity = tank;
                else if( (!tank_need_clarity && off_tank_need_clarity) || (tank_need_clarity && off_tank_need_clarity && tank.HealthPercent > off_tank.HealthPercent) )
                    tank_to_clarity = off_tank;

                if (tank_to_clarity != null && !Disc_healInterrDispClea_Manager.TargetDontHeal(tank_to_clarity))
                {
                    utils.LogActivity("TANKS CLARITY_OF_WILL", tank_to_clarity.SafeName);
                    return utils.Cast(CLARITY_OF_WILL, tank_to_clarity);
                }
            }
            return false;
        }
    }
}
